home *** CD-ROM | disk | FTP | other *** search
/ Night Owl 6 / Night Owl's Shareware - PDSI-006 - Night Owl Corp (1990).iso / 001a / mskrmsrc.zip / MSXIBM.ASM < prev    next >
Assembly Source File  |  1991-10-24  |  188KB  |  5,663 lines

  1. ; File MSXIBM.ASM
  2. ; Kermit system dependent module for IBM-PC
  3.     include mssdef.h
  4. ;       Copyright (C) 1982,1991, Trustees of Columbia University in the
  5. ;       City of New York.  Permission is granted to any individual or
  6. ;       institution to use, copy, or redistribute this software as long as
  7. ;       it is not sold for profit and this copyright notice is retained.
  8. ; Edit History
  9. ; 6 Sept 1991 version 3.11
  10. ; Last edit 6 Sept 1991
  11. ; 2 Feb 1991 Add support for user specified IRQs 2..15.
  12. ; 29 August Add direct Interconnections Inc TES support.
  13. ; 12 August Add Novell TELAPI network interface.
  14. ; 11 March 1990 Add 75/1200 baud split speed from Dan Norstedt.
  15. ; 30 Sept 1989 Incorporate Opennet networking material from Fred Richter.
  16. ; 30 Sept 1989 Fred Richter (FGR) Intel Corp, Hauppauge NY
  17. ;  polyof!inthap!fred or fred@polyof.poly.edu
  18. ;  Added support for Intel Opennet Networking Virtual Terminal Services
  19. ;  added "set port opennet xxx", also modified (slightly)
  20. ;  the Netbios code (rpost) to always have the next Netbios receive posted
  21. ;  as a small efficiency gain. Added error checking for received Netbios
  22. ;  packets (there was none for async receives), also fix problem when the
  23. ;  receives are canceled, where the data was being accepted anyway.
  24. ; 3 Sept 1989 Add DECnet CTERM and LAT support, plus Novell Int 6Bh.
  25. ; 9 July 1989 Add automatic usage of National Semiconductor 16550A UART in
  26. ;  receiver fifo mode. Thanks to Dan Norstedt, danne@kicki.stacken.kth.se,
  27. ;  and Campbell Scientific, Logan Utah for urging and supporting information.
  28. ; 17 June 1989 Add transparent interrupt driven support for IBM's Extended
  29. ;  Bios via SET PORT BIOSn.
  30. ; 8 June 1989 Add Wyse-700 support from (Mikko Laanti (mjl).
  31. ; 6 March 1989 Add SET TERMINAL REPLAY FILESPEC command.
  32. ; 21 Jan 1989 Avoid initializing a port until the port is accessed for regular
  33. ;  use, baud rate setting, or modem status. portin=-1 means unaccessed.
  34. ; 2 Dec 1988 Preserve UART parity etc bits in Line Control Reg.
  35. ; 30 Nov 1988 Add SET TERM CLEAR screen clear command (uses byte VTCLEAR).
  36. ; 26 Nov 1988 Add SET TERM TAB SET/CLEAR AT start-col:spacing notation.
  37. ; 21 Nov 1988 Version 2.32
  38. ; 25 Oct 1988 Add Ungermann Bass network board status check in proc chkub,
  39. ;  thanks to Fritz Buetikofer and Rene Rehmann in Switzerland.
  40. ; 9 Oct 1988 Add byte vtemu.vtchset to hold choices for VT102 emulator
  41. ;  character sets (US, UK, or Alternate-ROM). Tnx to Baruch Cochavy. The value
  42. ;  of vtemu.vtchset must match definitions in emulator file mszibm.asm.
  43. ; 5 Oct 1988 Add SET TERMINAL DIRECTION command and status display line.
  44. ; 21 August 1988 Move tests for NUL and DEL received chars to prtchr routine
  45. ;  for uniform application of tests.
  46. ; 28 July 1988 Add more UB details from Henrik Levkowetz. Double check serial
  47. ;  port address for 02f8h with COM1, for PCjr, and shift to COM2 addresses.
  48. ; 16 July 1988 Use null interrupt routine, nulint, when resetting serial port
  49. ;  because setting OUT2 low generates stray ints on some UARTs. [jrd]
  50. ; 1 July 1988 Version 2.31
  51. ; 12 June 1988 Add small changes to handle network session failures, and
  52. ;  add carry set if serini fails to init port.
  53. ; 29 May 1988 Add Ungermann Bass NetOne NETCI support from Henrik Levkowetz
  54. ;  [ohl]. Revise same to test for actual network presence and to avoid
  55. ;  interference with NetBios operations. Use "SET PORT UB-Net1"
  56. ; 23 May 1988 Hangup now resets serial port so can be re-inited with DTR high
  57. ; 21 May 1988 Tweak serrst to allow stray interrupts while resetting UART,
  58. ;  clear outstanding network requests when changing ports.
  59. ; 6 May 1988 Introduce xmtbufx for explict network double buffering of
  60. ;   xmitted data.
  61. ; 28 April 1988 fix set port bios register problem.
  62. ; 18 April 1988 Network: do another READ when char count < low water mark.
  63. ;  If BIOSn is selected skip test of Bios 40:0h for port presence.
  64. ; 3 April 1988 Ignore NUL and DEL at serial port unless DEBUG or TRANSLATE
  65. ;  INPUT are active, but pass DEL if Tek mode is active. Replace netdone
  66. ;  with new lclexit global word to shut net when Kermit exits.
  67. ; 22 March 1988 Add global byte Tekgraf which forces graphics board type
  68. ;   0=auto-sensing, 1=cga, 2=ega, 3=VGA, 5=Hercules, 5=ATT. Tekgraf stored
  69. ;   and set in this file by Set Term Graphics <board type>. [jrd]
  70. ; 6 March 1988 Ignore received XOFF's if we have already sent one. [jrd]
  71. ; 27 Feb 1988 Add global routine getmodem to return modem status in al. [jrd]
  72. ; 9 Feb 1988 Automaticallly find Interrupt ReQuest level for a port.
  73. ;   No Modem Status for network. [jrd]
  74. ; 25 Jan 1988 Revise outchr waiting on XON to use 4 millisec increments. [jrd]
  75. ; 1 Jan 1988 version 2.30
  76. ; 24 Dec 1987 Revise selection of COM1 to use COM1 name but COM2 addresses
  77. ;  if base address of 02f8 (COM2) is found in 40:00h and display notice.
  78. ;  Restore state of IRQ interrupt line when finished with serial port. [jrd]
  79. ; 31 Oct 1987 Add terminal type Tek4010, with Tek submode Tekflg. [jrd]
  80. ; 24 Oct 1987 Enhance clrbuf to empty any intermediate (net) buffers. [jrd]
  81. ; 19 Oct 1987 Fix stray tab-set at column 32. [jrd]
  82. ; 2 Oct 1987 Add PCjr baud rate table, from Ted Medin. [jrd]
  83. ; 6 Sept 1987 Allow serial port serint to send xoff when buffer fills even
  84. ;  though user may have sent xoff by hand. [jrd]
  85. ; 27 Aug 1987 Skip timeout test in OUTCHR if receive timeout is zero. [jrd]
  86. ; 23 August 1987 Add vtemu.vtflgop to hold runtime terminal settings so that
  87. ;  a reset command restores them to the Setup values, vtemu.vtflgst. Show
  88. ;  displays the vtemu.vtflgop operational values. [jrd]
  89. ; 17 August 1987 Make timing adjustments for Token Passing and single buffered
  90. ;  network adapter boards. Byte netdbfr indicates presence of double buffering;
  91. ;  it is set in chknet as a vendor option. To test your boards force dbl buf
  92. ;  then look for missing 256 byte parts of long packets sent out; missing parts
  93. ;  mean new material overwrote not-yet-sent old == single buffering. [jrd]
  94. ; 8 August 1987 Add interrupt chaining in serint. [jrd]
  95. ; 23 July 1987 Clear xofsnt and xofrcv xon/xoff flags in ihost(s/r). [jrd]
  96. ; 9 July 1987 Cure confusion about COM1/2 for IBM PCjr (address of regular
  97. ;  COM2 in 40:0h slot for COM1) with info from John Neufeld. [jrd]
  98. ; 2 July 1987 Route NetBios cancels through separate scb for systems, such
  99. ;  as Novell NetWare, which object to having active scbs touched. [jrd]
  100. ; 25 June 1987 Add trapping of Int 14H (Bios RS232 procedure) to allow
  101. ;  CTTY command to function without too much inteference from DOS. [jrd]
  102. ; 17 June 1987 Enlarge tab setting to full 132 columns at all times. [jrd]
  103. ; 11 June 1987 Add Set Term Roll on/off to control auto roll back of screen
  104. ;  when new characters are displayed; default is off (no unwinding). [jrd]
  105. ; 20 May 1987 Remove rejection of NULL and DEL chars, let callers do it. [jrd]
  106. ; 16 May 1987 Add distinction between user typed and receiver threshold
  107. ;  controlled sending of XOFF. User level overrides buffer control.[jrd]
  108. ;  Add COM3 and COM4 support: examine memory 40:00h->40:07h for selected
  109. ;  port COM1..4, resp. If word is null then set flags.comflg to 0 to say
  110. ;  undefined port. Otherwise, use that word in seg 40h as base of UART i/o
  111. ;  ports. Assume IRQ4 for COM1 and COM3 (same except for port addresses)
  112. ;  and IRQ4 for  COM2 and COM4 (again, same except for port addresses).
  113. ;  Serial port info sturcture (not values) assumed identical for all ports.
  114. ; 25 April 1987 Add Netbios compatible local area network support. [jrd]
  115. ;  Set Port command expanded to syntax SET PORT NET nodename. Use nodename
  116. ;  if acting as a client to named remote node, leave blank if running in
  117. ;  Server mode. Byte 'ttyact' is controlled by msster.asm to indicate Connect
  118. ;  mode is being used. Byte 'netdone' (stored in mssker.asm) holds offset of
  119. ;  network hangup procedure 'netclose' to be done when leaving Kermit. Hangup
  120. ;  command extended to to network hangup as well. Network uses IBM Netbios
  121. ;  standard calls (Int 5Ch) and allows for extensions of AT&T STARLAN for
  122. ;  longer node names via Int 2Bh (the later is tested before use). Virtual
  123. ;  circuits are employed. The Redirector is not necessary. Kermit can operate
  124. ;  as either a terminal (does a CALL at Connect mode startup), a file receiver
  125. ;  (does a CALL at startup), or a Kermit server (does an anonomous LISTEN at
  126. ;  startup, hence no nodename). Clients should Set Timer Off.
  127. ; Note -
  128. ; When the Bios is used for serial port i/o the modem signals DSR and CTS
  129. ; must be asserted low before the Bios will access the hardware. Jumpers
  130. ; from pin 20 (DTR) to pin 6 (DSR) and from pin 4 (RTS) to pin 5 (CTS)
  131. ; will probably be necessary.
  132. ;       From Glenn Everhart (who suggested using the Bios alternative)
  133. ;
  134.     public    serini, serrst, clrbuf, outchr, coms
  135.     public    dodel, ctlu, cmblnk, locate, prtchr, baudst, clearl
  136.     public    getbaud, beep, shomodem, getmodem, mdmhand
  137.     public    count, xofsnt, puthlp, putmod, clrmod, poscur, holdscr
  138.     public    sendbr, sendbl, machnam, setktab, setkhlp, lclini, showkey
  139.     public    ihosts, ihostr, dtrlow, serhng, comptab, pcwait
  140.     public    portval, bdtab, ubhold, dupflg, setnbios
  141.  
  142. off    equ    0
  143. bufon    equ    1        ; buffer level xon/xoff on-state control flag
  144. usron    equ    2        ; user level xon/xoff on-state control flag
  145.  
  146. mntrgh    equ    bufsiz*3/4    ; High point = 3/4 of buffer full
  147. mntrgl    equ    bufsiz/4    ; Low point = 1/4 buffer full
  148.  
  149. BRKBIT    EQU    040H        ; Send-break bit. 
  150. TIMERCMD EQU    43h        ; 8253/4 Timer chip command port
  151. TIMER2DATA EQU    42h        ; 8253/4 Timer 2 data port
  152. PPI_PORT EQU    61h        ; 8255 prog peripheral chip control port
  153. VIDEO    EQU    10H        ; Bios Video display software interrupt
  154. RS232    EQU    14H        ; Bios RS232 serial port s/ware interrupt
  155.  
  156. ; constants used by serial port handler
  157. MDMINP    EQU    1        ; Input ready bit
  158. MDMOVER    EQU    2        ; Receiver overrun
  159.                 ; 1200/75 baud split speed constants
  160. cnt75b    equ    47721/3        ; One bit of 75 baud at 1.193 Mhz clock
  161. precomp    equ    cnt75b/8    ; Precomp 12%, allows 3ms latency w 12% jitter
  162.  
  163. _TEXT    segment
  164.     extrn    ktcpstart:far, ktcpstop:far
  165. _TEXT    ends
  166.  
  167. data     segment
  168.     extrn    flags:byte, trans:byte, ttyact:byte, comand:byte
  169.     extrn    lclsusp:word, lclrest:word, lclexit:word, rxtable:byte
  170.     extrn    rdbuf:byte, taklev:byte, tekflg:byte, scbattr:byte
  171.     extrn    low_rgt:word, diskio:byte, crt_cols:byte, repflg:byte
  172.     extrn    dosnum:word, portirq:byte, dosctty:byte, decbuf:byte
  173.     extrn    tcpdata:word, tcphost:byte, tv_mode:byte
  174.  
  175. ; Modem information
  176. mdminfo    struc
  177. mddat    dw    0        ; data register, base address (03f8h)
  178. mdiir    dw    0        ; interrupt identification register (03fah)
  179. mdstat    dw    0        ; line status register (03fdh)
  180. mdcom    dw    0        ; line control register (03fbh)
  181. mden    db    0        ; mask to enable interrupt
  182. mddis    db    0        ; mask to disable interrupt
  183. mdmeoi    db    0        ; specific EOI
  184. mdintv    dw    0        ; saved interrupt vector (0ch is IRQ 4)
  185. mdmintc    dw    0        ; interrupt controller control (20h or 0a0h)
  186. mdminfo    ends
  187. modem    mdminfo <>
  188.  
  189. setktab    db    0        ; superceded by msuibm code, return 0 here
  190. setkhlp    db    '$'        ; and add empty help string
  191. holdscr    db    0        ; Hold-Screen, non-zero to stop reading
  192. savsci    dd    0        ; old serial port interrupt vector
  193. sav232    dd    0        ; Original Bios Int 14H address, in Code seg
  194. savirq    db    0        ; Original Interrupt mask for IRQ
  195. savier    db    0        ; original UART Int enable bits (03f9)
  196. savstat db    0        ; orginal UART control reg  (03fch)
  197. savlcr    db    0        ; Original Line Control Reg (3fbh) contents
  198. dupflg    db    0        ; full (0) or half (1) duplex on port
  199. quechar    db    0        ; queued char for outchr (XOFF typically)
  200. intkind    db    0        ; cause of serial port interrupt
  201. isps2    db    0        ; non-zero if real IBM PS/2
  202. erms40    db    cr,lf,'?Warning: Unrecognized Speed',cr,lf,'$'
  203. badbd    db    cr,lf,'Unimplemented speed$'
  204. badprt    db    cr,lf,'?Warning: no hardware for this serial port$'
  205. biosmsg    db    cr,lf,'?This port will be operated through the Bios as BIOS$'
  206. msmsg1    db    cr,lf,'  Modem is not ready: DSR is off$'
  207. msmsg2    db    cr,lf,'  Modem is ready:     DSR is on$'
  208. msmsg3    db    cr,lf,'  no Carrier Detect:  CD  is off$'
  209. msmsg4    db    cr,lf,'  Carrier Detect:     CD  is on$'
  210. msmsg5    db    cr,lf,'  no Clear To Send:   CTS is off$'
  211. msmsg6    db    cr,lf,'  Clear To Send:      CTS is on$'
  212. msmsg7    db    cr,lf,'  Modem is not used by the Network$'
  213. msmsg8    db    cr,lf,'  COM1 address:       Port \x$'
  214. msmsg9    db    ', IRQ $'
  215. hngmsg    db    cr,lf,' The phone or network connection should have hung up'
  216.     db    cr,lf,'$'
  217. hnghlp    db    cr,lf,' The modem control lines DTR and RTS for the current'
  218.     db    ' port are forced low (off)'
  219.     db    cr,lf,' to hangup the phone. Normally, Kermit leaves them'
  220.     db    ' high (on) when it exits.',cr,lf
  221.     db    ' For networks, the active session is terminated.',cr,lf,'$'
  222.  
  223. machnam    db    'IBM-PC$'
  224. crlf    db    cr,lf,'$'
  225. delstr  db    BS,BS,'  ',BS,BS,'$'     ; Delete string
  226. clrlin  db    BS,BS,'  ',cr,'$'    ; Clear line (just the cr part)
  227. portin    db    -1        ; Has comm port been initialized, -1=not used
  228. xofsnt    db    0        ; Say if we sent an XOFF
  229. xofrcv    db    0        ; Say if we received an XOFF
  230. parmsk    db    0ffh        ; parity mask, 0ffh for no parity, 07fh with
  231. flowoff    db    0        ; flow-off char, Xoff or null (if no flow)
  232. flowon    db    0        ; flow-on char, Xon or null
  233. flowcnt    db    0        ; holds flowc (!= 0 using any flow control)
  234. pcwcnt    dw    800        ; number of loops for 1 millisec in pcwait
  235. temp    dw    0
  236. temp2    dw    0
  237. tempsci dw    0        ; temp storage for serint
  238. tempdum    dw    0        ; temp storage for serdum
  239. timeract db    0        ; timer in use by a routine, flag
  240.  
  241. comptab    db    23            ; communications port options
  242.     mkeyw    'Bios1','0'+1        ; '0' is to flag value as forced Bios
  243.     mkeyw    'Bios2','0'+2
  244.     mkeyw    'Bios3','0'+3
  245.     mkeyw    'Bios4','0'+4
  246.     mkeyw    'COM1',1        ; these go straight to the hardware
  247.     mkeyw    'COM2',2
  248.     mkeyw    'COM3',3
  249.     mkeyw    'COM4',4
  250.     mkeyw    '1',1            ; straight to the hardware
  251.     mkeyw    '2',2
  252.     mkeyw    '3',3
  253.     mkeyw    '4',4
  254.     mkeyw    '3Com(BAPI)','C'    ; 3Com BAPI interface
  255.     mkeyw    'DECnet','D'        ; DECnet-DOS LAT and CTERM
  256.     mkeyw    'EBIOS','E'        ; IBM/YALE EBIOS Int 14h interceptor
  257.     mkeyw    'NetBios','N'        ; Netbios
  258.     mkeyw    'Novell(NASI)','W'    ; Novell NetWare NASI/NACS
  259.     mkeyw    'OpenNET','O'        ; Intel OpenNET support (FGR)
  260.     mkeyw    'TCP/IP','t'        ; Telnet, internal
  261.     mkeyw    'TELAPI','T'        ; Novell TELAPI
  262.     mkeyw    'TES','I'        ; TES, Interconnections Inc
  263.     mkeyw    'UB-Net1','U'        ; Ungermann Bass Net One
  264.     mkeyw    '   ',0            ; port is not present, for Status
  265.  
  266. portmax    equ    4            ; number of predefined ports
  267.  
  268. port1    prtinfo    <0FFFH,0,defpar,1,0,defhand,floxon,0>    ; UART ports
  269. port2    prtinfo    <0FFFH,0,defpar,1,0,defhand,floxon,0>
  270. port3     prtinfo    <0FFFH,0,defpar,1,0,defhand,floxon,0>
  271. port4    prtinfo    <0FFFH,0,defpar,1,0,defhand,floxon,0>
  272.     rept    portmax-4
  273.     prtinfo    <0FFFH,0,defpar,1,0,defhand,floxon,0>
  274.     endm
  275. portb1    prtinfo    <0FFFH,0,defpar,1,0,defhand,floxon,0>    ; Bios ports
  276. portb2    prtinfo    <0FFFH,0,defpar,1,0,defhand,floxon,0>
  277. portb3     prtinfo    <0FFFH,0,defpar,1,0,defhand,floxon,0>
  278. portb4    prtinfo    <0FFFH,0,defpar,1,0,defhand,floxon,0>
  279.  
  280. portval    dw    port1            ; Default is to use port 1
  281.  
  282. bdtab    db    19            ; Baud rate table
  283.     mkeyw    '45.5',0
  284.     mkeyw    '50',1
  285.     mkeyw    '75',2
  286.     mkeyw    '110',3
  287.     mkeyw    '134.5',4
  288.     mkeyw    '150',5
  289.     mkeyw    '300',6
  290.     mkeyw    '600',7
  291.     mkeyw    '1200',8
  292.     mkeyw    '1800',9
  293.     mkeyw    '2000',10
  294.     mkeyw    '2400',11
  295.     mkeyw    '4800',12
  296.     mkeyw    '9600',13
  297.     mkeyw    '19200',14
  298.     mkeyw    '38400',15
  299.     mkeyw    '57600',16
  300.     mkeyw    '115200',17
  301.     mkeyw    '75/1200',18    ; split speed, use this index for Bsplit
  302.  
  303. Bsplit    equ    18        ; 75/1200 baud, split-speed  [pslms]
  304.  
  305. ; this table is indexed by the baud rate definitions given in bdtab.
  306. ; Unsupported baud rates should contain 0FFh.
  307.  
  308. bddat    label    word
  309.     dw    9E4H        ; 45.5 baud
  310.     dw    900H        ; 50 baud
  311.     dw    600H        ; 75 baud
  312.     dw    417H        ; 110 baud
  313.     dw    359H        ; 134.5 baud
  314.     dw    300H        ; 150 baud
  315.     dw    180H        ; 300 baud
  316.     dw    0C0H        ; 600 baud
  317.     dw    60H        ; 1200 baud
  318.     dw    40H        ; 1800 baud
  319.     dw    3AH        ; 2000 baud
  320.     dw    30H        ; 2400 baud
  321.     dw    18H        ; 4800 baud
  322.     dw    0CH        ; 9600 baud
  323.     dw    06H        ; 19200 baud
  324.     dw    03H        ; 38400 baud
  325.     dw    02h        ; 57600 baud
  326.     dw    01h        ; 115200 baud
  327.     dw    5fh        ; Split 75/1200, 1200+1.1 percent error
  328. baudlen    equ    ($-bddat)/2    ; number of entries above
  329.  
  330. jrbddat    label    word        ; Baud rate table for IBM PCjrs [tm]
  331.     dw    0FFH        ; 45.5 baud  -- Not supported
  332.     dw    8bfH        ; 50 baud
  333.     dw    5d3H        ; 75 baud
  334.     dw    3f9H        ; 110 baud
  335.     dw    340H        ; 134.5 baud
  336.     dw    2e9H        ; 150 baud
  337.     dw    175H        ; 300 baud
  338.     dw    0baH        ; 600 baud
  339.     dw    5dH        ; 1200 baud
  340.     dw    3eH        ; 1800 baud
  341.     dw    38H        ; 2000 baud
  342.     dw    2fH        ; 2400 baud
  343.     dw    18H        ; 4800 baud
  344.     dw    0CH        ; 9600 baud
  345.     dw    06H        ; 19200 baud
  346.     dw    03H        ; 38400 baud
  347.     dw    02h        ; 57600 baud
  348.     dw    01h        ; 115200 baud
  349.     dw    5eh        ; Split 75/1200, 1200+1.1 per cent error
  350.  
  351. ; this table is indexed by the baud rate definitions given in
  352. ; pcdefs.  Unsupported baud rates should contain FF.
  353. ; Bits are for Bios speed, no parity, 8 data bits. [jrd]
  354. clbddat   label   word
  355.         dw      0FFH            ; 45.5 baud  -- Not supported
  356.         dw      0FFH            ; 50 baud
  357.         dw      0FFH            ; 75 baud
  358.         dw      03H        ; 110 baud
  359.         dw      0FFH            ; 134.5 baud
  360.         dw      23H        ; 150 baud
  361.         dw      43H        ; 300 baud
  362.         dw      63H        ; 600 baud
  363.         dw      83H        ; 1200 baud
  364.         dw      0ffH        ; 1800 baud
  365.         dw      0FFH        ; 2000 baud
  366.         dw      0a3H        ; 2400 baud
  367.         dw      0c3H        ; 4800 baud
  368.         dw      0e3H        ; 9600 baud
  369.         dw      0FFH        ; 19200 baud
  370.         dw      0FFH        ; 38400 baud
  371.     dw    0FFH        ; 57600 baud
  372.     dw    0FFH        ; 115200 baud
  373.     dw    0FFh        ; Split 75/1200
  374.  
  375. ; variables for serial interrupt handler
  376. source    db    bufsiz+2 DUP(?)    ; Buffer for data from port (+ 2 guard bytes)
  377. srcpnt    dw    source        ; Pointer in buffer (DI)
  378. count    dw    0        ; Number of chars in int buffer
  379. mst    dw    0        ; Modem status address
  380. mdat    dw    0        ; Modem data address
  381. miir    dw    0        ; modem interrupt ident register
  382. mdeoi    db    0        ; End-of-Interrupt value
  383. mdmhand    db    0        ; Modem status register, current
  384. mdintc    dw    0        ; interrupt control address
  385.  
  386. ; Information structures for IBM Netbios compatible Local Area Networks
  387.                 ; network constants
  388. netint    equ    5ch        ; Netbios interrupt
  389. nadd    equ    30h        ; Add name
  390. ncall    equ    10h        ; CALL, open a virtual circuit session
  391. ncancel    equ    35h        ; Cancel command in scb buffer
  392. ndelete    equ    31h        ; Delete Name
  393. nhangup    equ    12h        ; Hangup virtual circuit session
  394. nlisten    equ    11h        ; Listen for session caller
  395. naustat    equ    33h        ; Network Adapter Unit, get status of
  396. nreceive equ    15h        ; Receive on virtual circuit
  397. nreset    equ    32h        ; Reset NAU and tables
  398. nsend    equ    14h        ; Send on virtual circuit
  399. nsestat    equ    34h        ; Session, get status of
  400. netbrk    equ    70h        ; STARLAN Int 5bh send Break
  401. nowait    equ    80h        ; no-wait, command modifier
  402. npending equ    0ffh        ; Pending request
  403. exnbios    equ    0400h        ; Int 2ah exec netbios call, error retry
  404. nbuflen    equ    512        ; bytes in each network buffer (two of them)
  405.                 ;  DEC-LAT requires 259 (256 + 3 extra)
  406.  
  407.                 ; nettype word bits
  408. starlan    equ    0001h        ; AT&T STARLAN
  409. netone    equ    0002h        ; Ungermann-Bass Net/One
  410. decnet    equ    0004h        ; DECnet CTERM
  411. declat    equ    0008h        ; DECnet LAT
  412. bapi    equ    0010h        ; 3Com BAPI
  413. ebios    equ    0020h        ; EBIOS, IBM and YALE
  414. telapi    equ    0040h        ; TELAPI, Novell
  415. tes    equ    0080h        ; TES, Interconnections Inc and Novell
  416. tcpnet    equ    0100h        ; TCP/IP
  417. netbios    equ    8000h        ; NetBios
  418.  
  419. nettype    dw    0        ; kind of local area net (vendor bit field)
  420.  
  421. ;xncall    equ    74h        ; [ohl] Net/One extended call function
  422. netci    equ    6Bh        ; [ohl] Net/One command interface interrupt,
  423.                 ; [ohl]  used for the following functions:
  424. nciwrit equ    0000h        ; [ohl] Net/One write function
  425. nciread equ    0100h        ; [ohl] Net/One read function
  426. ncistat equ    0700h        ; [ohl] Net/One status function
  427. ncicont equ    0600h        ; [ohl] Net/One control function
  428. ncibrk    equ    02h        ; [ohl] Net/One code for a break
  429. ncidis    equ    04h        ; [ohl] Net/One code for disconnect
  430. ncihld    equ    06h        ; [ohl] code for placing a connection on hold
  431. bapiint    equ    14h        ; 3Com BAPI, interrupt (Bios replacment)
  432. bapicon    equ    0a0h        ; 3Com BAPI, connect to port
  433. bapidisc equ    0a1h        ; 3Com BAPI, disconnect
  434. bapiwrit equ    0a4h        ; 3Com BAPI, write block
  435. bapiread equ    0a5h        ; 3Com BAPI, read block
  436. bapibrk    equ    0a6h        ; 3Com BAPI, send short break
  437. bapistat equ    0a7h        ; 3Com BAPI, read status (# chars to be read)
  438. bapihere equ    0afh        ; 3Com BAPI, presence check
  439. bapieecm equ    0b0h        ; 3Com BAPI, enable/disable ECM char
  440. bapiecm    equ    0b1h        ; 3Com BAPI, trap Enter Command Mode char
  441.                 ;
  442. telport    equ    23        ; Telnet port
  443. telopen    equ    0e0h        ; xtelopen a connection
  444. telclose equ    0e1h        ; xtelclose a connection
  445. telread    equ    0e2h        ; xtelread char(s)
  446. telwrite equ    0e3h        ; xtelwrite chars
  447. telioctl equ    0e4h        ; xtelioctl, ioctl the port
  448. telreset equ    0e5h        ; xtelreset, reset the whole TELAPI package
  449. telunload equ    0e6h        ; xtelunload, unload TELAPI TSR
  450. tellist    equ    0e7h        ; xtellist, list current sessions and status
  451. telattach equ    0e8h        ; xtelattach, session to COM port # 0..3
  452. telportosn equ    0e9h        ; xtelportosn, return session id for port
  453. telunreac equ    -51        ; network is unreachable
  454. telinuse equ    -56        ; socket already in use
  455. teltmo    equ    -60        ; timeout on connection attempt
  456. telrefuse equ    -61        ; connection refused
  457. teldwnhost equ    -64        ; host is down
  458. telunkhost equ    -67        ; unknown host
  459. telfull    equ    -301        ; all sessions are in use
  460.                 ; TELAPI messages and misc data
  461. telhlp    db    'Internet address nnn.nnn.nnn.nnn$'
  462. telmsg1    db    cr,lf,'?Badly constructed Internet address: $'
  463. telmsg2    db    cr,lf,'?No connection. Status = -$'
  464. telmsg51 db    cr,lf,'?Network is unreachable$'
  465. telmsg56 db    cr,lf,'?Socket already in use$'
  466. telmsg60 db    cr,lf,'?Timeout on connection attempt$'
  467. telmsg61 db    cr,lf,'?Connection refused$'
  468. telmsg64 db    cr,lf,'?Host is down$'
  469. telmsg67 db    cr,lf,'?Unknown host$'
  470. telmsg301 db    cr,lf,'?All sessions are in use$'
  471. telstate dw    7        ; TELAPI Char/Line mode (Char mode = 7)
  472. telhostid db    2 dup (0)    ; Telnet internal host session ident
  473. teloption dw    5 dup (0)    ; Telnet Options data word/string ptr
  474.                 ;
  475. testalk    equ    4        ; TES invoke interactive cmd interpreter
  476. tesbwrite equ    6        ; TES block write
  477. tesbread equ    7        ; TES block read
  478. tesinstal equ    0a0h        ; TES installation/status report
  479. teslist    equ    0a1h        ; TES get list of sessions, with status    
  480. tesgets    equ    0a2h        ; TES get list of server names
  481. tesnews    equ    0a3h        ; TES start a new session
  482. tesholds equ    0a4h        ; TES hold currently active connection
  483. tesresume equ    0a5h        ; TES resume a session (1..9)
  484. tesdrop    equ    0a6h        ; TES drop a session
  485. tesnexts equ    0a7h        ; TES skip to next active session
  486. tesexec    equ    0a8h        ; TES send string to cmd interpreter
  487. tesport    dw    0        ; TES low byte = intercepted port
  488. tesquiet db    'ACTION NONE',0 ; TES Stop command prompting
  489. tesses    db    0        ; TES session number (1..9 is legal)
  490. tesname    db    50 dup (0)    ; TES host name asciiz
  491. teshelp    db    cr,lf,'?Host name or "*" to see available hosts'
  492.     db    ' or press ENTER to resume a connection$'
  493. tesnlist db    cr,lf,'  Active TES hosts:$'
  494. tesnhost db    cr,lf,'?No existing connection.'
  495.     db    ' Please select a host with  SET PORT TES host$'
  496.  
  497. ;; pcnet values:    0    no network available at all
  498. ;;            1    network board reports itself as present
  499. ;;            2    and session is in progress
  500. ;; extrn byte pcnet is  defined in msster.
  501.  
  502. portn    prtinfo    <0FFFH,0,defpar,1,0,defhand,floxon,0> ; port struc for PORTN
  503.  
  504. xmtbuf    db    nbuflen dup (0) ; network buffer for transmitter
  505. xmtcnt    dw    0        ; occupancy in current output buffer
  506. xmtbufx    db    nbuflen+3 dup (0) ; external version of xmtbuf (dbl buffers)
  507. rcvbuf    db    nbuflen+3 dup (0) ; network buffer for receiver
  508.  
  509. scbst struc            ; Session (Network) Control Block [PCnet comp]
  510.     scb_cmd        db 0    ; command code for Netbios Int 5ch
  511.     scb_err        db 0    ; error return or request is pending
  512.     scb_vcid    db 0    ; virtual circuit ident number
  513.     scb_num        db 0    ; local name-number
  514.     scb_baddr    dw 0    ; buffer address, offset
  515.             dw data ;  and segment
  516.     scb_length    dw 0    ; length of buffer data
  517.     scb_rname    db '*               ' ; remote name, 16 chars space
  518.     scb_lname    db '                ' ; local name      filled 
  519.             db 0    ; Receive timeout (0.5 sec units), want 0
  520.             db 0    ; Send timeout (0.5 sec units), want 0
  521.     scb_post    dw 0    ; interrupt driven post address, offset
  522.             dw code ;  and segment
  523.             db 0    ; LAN_num (adapter #), set to zero for STARLAN
  524.     scb_done    db 0    ; command complete status
  525.                 ; the 14 bytes below are normally 'reserved'
  526.                 ; STARLAN uses 5 for long/special call names
  527.                 ;  together with STARLAN specific Int 5bh
  528.     scb_vrname    dw 0,0    ; Variable length call name ptr offset,segment
  529.     scb_vrlen    db 0    ; length of vrname
  530.             db 9 dup (0)    ; reserved
  531. scbst    ends
  532. rcv    scbst    <,,,,rcvbuf,,length rcvbuf,,,,,rpost>; declare scb for rcvr
  533. xmt    scbst    <,,,,xmtbuf,,length xmtbuf,,,,,spost>;  for xmtr
  534. lsn    scbst    <,,,,xmtbuf,,length xmtbuf,,,,,lpost>;  for server listen
  535. can    scbst    <>                     ;  for cancels
  536.                     ; DECnet material
  537. decint    equ    69h            ; CTERM interrupt
  538. dpresent equ    100h            ; CTERM Installation check
  539. dsend    equ    101h            ; CTERM send byte
  540. dread    equ    102h            ; CTERM read byte
  541. dcstat    equ    103h            ; CTERM status
  542. ddstat    equ    104h            ; CTERM Decnet status
  543. dopen    equ    105h            ; CTERM open session
  544. dclose    equ    106h            ; CTERM close session
  545. dgetscb    equ    10ah            ; CTERM get SCB size
  546.  
  547. latint    equ    6ah            ; LAT interrupt
  548. latsend equ    1            ; LAT send byte
  549. latread    equ    2            ; LAT read byte
  550. latstat    equ    3            ; LAT status
  551. latinfo    equ    6            ; LAT get miscellaneous information
  552. latsrv    equ    0d500h            ; LAT get next service name
  553. latopen    equ    0d0ffh            ; LAT open
  554. latclose equ    0d000h            ; LAT close
  555. latbreak equ    0d100h            ; LAT send a BREAK
  556. latscbget equ    0d800h            ; LAT get SCB interior to LAT
  557. latscbfree equ    0d801h            ; LAT free SCB interior to LAT
  558. latcpyems equ    0d900h            ; LAT copy to/from SCB in EMS or not
  559.  
  560. decneth    dw    0            ; CTERM session handle
  561. decseg    dw    0            ; segment of CTERM SCB memory block
  562. lathand    dw    0            ; LAT session handle, high byte = 0ffh
  563. latseg    dw    0            ; LAT SCB seg in our memory
  564. latinems db    0            ; LAT SCB is in EMS, if non-zero
  565. latversion db    4            ; LAT major version number
  566. latscbptr dd    0            ; LAT, pointer to SCB
  567.  
  568. lcbst    struc                ; LAT control block structure V4
  569.     service    db    17 dup (0)    ; 0 service     (number is offset)
  570.         db    10 dup (0)    ; 17 node, for future use
  571.     lat_pwd    dd    0        ; 27 password buffer ptr
  572.     pwd_len    db    0        ; 31 length of the buffer
  573.         db    22 dup (0)    ; 32 reserved
  574.     stopped    dd    0        ; 54 session stopped post routine addr
  575.     overflow dd    0        ; 58 service table overflow post addr
  576.     xnotify    dd    0        ; 62 transmit post routine addr
  577.     rnotify    dd    0        ; 66 receive post routine addr
  578.     sstatus    dw    0        ; 70 session status
  579.         db    270 dup (0)    ; 72 reserved
  580.     slotqty    db    2        ; 342 number receive data slots
  581.     slotused db    0        ; 343 number occupied slots
  582.     slotnr    db    0        ; 344 index of next rcv slot to use
  583.     slotcur    db    0        ; 345 index of current rcv slot
  584.     slotptr dw    0        ; 346 ptr to first received char
  585.     slottbl    dw    0        ; 348 ptrs to bufs for slot 1
  586.         dw    0        ; 350 and for slot 2
  587.     slotbf1 db    259 dup (0)    ; 352 first receive buffer
  588.     slotbf2 db    259 dup (0)    ; 611 second receive buffer
  589. lcbst    ends                ; total of 870 bytes
  590.  
  591. latservice db    17 dup (0)
  592. latpwd    db    16 dup (0),0        ; LAT password, terminator
  593. decmsg1    db    cr,lf,'Cannot create DECnet session.$'
  594. decmsg3    db    ' DECnet Error $'
  595. decmsg4    db    cr,lf,' DECnet CTERM ready$'
  596. decmsg5    db    cr,lf,' DECnet LAT ready$'
  597.                 ; end of DECnet
  598.  
  599. pcnet    db    0        ; Network is functioning
  600. nambuf    db    65 dup (0)    ; network long name storage (STARLAN)
  601. newnambuf db    0        ; non-zero if new entry into namebuf above
  602. internet db    4 dup (0)    ; TELAPI Internet address, binary
  603. telses    dw    0        ; TELAPI session number
  604. sposted    db    0        ; send interlock, 0 if no send posted
  605. rposted    db    0        ; rcv interlock, 0 if no receive posted
  606. lposted    db    0        ; listen outstanding (if non-zero)
  607. netdbfr    db    0        ; non-zero if net board is double buffered
  608. lnamestat db    0        ; status of local name 0 = default,
  609.                 ;  1 = specified by user, 2 = locked in
  610. deflname db    'mskermit.K      ' ; default local name, 16 bytes
  611. ivt1str    db    'iVT1',0    ; FGR - OpenNet VT handshake string
  612. inettyp    db    0        ; FGR - network type 'N' or 'O'
  613. nsbrk    dw    0        ; net can send Break
  614. chkmsg1    db    cr,lf,'?Cannot construct a local Kermit name, error = $'
  615. setnbad db    cr,lf,'?Local Kermit NetBIOS name is already fixed.$'
  616. chkmsg2    db    cr,lf,lf,' Name $'
  617. chkmsg3    db    ' is already in use. Please enter another of',cr,lf
  618. setnbhlp db    ' 1 - 14 letters or numbers (or nothing to quit): $'
  619. netmsg1    db    cr,lf,' Checking if our node name is unique ...$'
  620. netmsg2    db    cr,lf,' The network is active, our name is $'
  621. netmsg3 db    cr,lf,'  NetBios local name: $'
  622. netmsg4    db    '  Remote host: $'
  623. netmsg5 db    cr,lf,'  DECnet host: $'
  624. netmsg6 db    cr,lf,'  TELAPI Internet host: $'
  625. netmsg7    db    cr,lf,'  TES host name: $'
  626. netmsg8    db    cr,lf,'  EBIOS server port name: $'
  627. nonetmsg db    cr,lf,'?The network is not available$'
  628. noname    db    cr,lf,'?No name exists for the remote host.$'
  629. nethlp    db    cr,lf,'  node name of remote system,'
  630.     db    cr,lf,'  or press ENTER to use current name,'
  631.     db    cr,lf,'  or press ENTER for server mode (NetBios only).$'
  632. dnethlp    db    cr,lf,'  node name of remote system,'
  633.     db    cr,lf,'  or press ENTER to use current name,'
  634.     db    cr,lf,'  or  *  to see a list of LAT service names.$'
  635. nethlp2    db    cr,lf,' Optional LAT password, if using a LAT connection$'
  636. dnetsrv    db    cr,lf,' Available LAT service names:',cr,lf,'$'
  637. ngodset    db    cr,lf,' Connecting to network node: $'
  638. nbadset    db    bell,cr,lf,'?Cannot reach network node: $'
  639. recmsg    db    cr,lf,'?Network receive failed, status = $'
  640. sndmsg    db    cr,lf,'?Network send failed, status = $'
  641. naskpmt    db    cr,lf,' A network session is active.',cr,lf
  642.     db    ' Enter RESUME to resume it or NEW to start a new session:',0
  643. nettab    db    2
  644.     mkeyw    'New',0
  645.     mkeyw    'Resume',1
  646.  
  647. ebbufset equ    0ffh            ; EBIOS set buf mode (1=send, 2=rcv)
  648. ebbufcnt equ    0fdh            ; EBIOS get buf count (1=send, 2=rcv)
  649. ebpace    equ    0feh            ; EBIOS set pacing mode (80h=send)
  650. ebrcv    equ    0fch            ; EBIOS receive, no wait
  651. ebsend    equ    1            ; EBIOS send a char
  652. ebmodem    equ    0fbh            ; EBIOS set modem leads
  653. ebbreak    equ    0fah            ; EBIOS send a BREAK
  654. ebcontrol equ    0f9h            ; EBIOS regain control
  655. ebredir equ    0f6h            ; EBIOS do port redirection
  656. ebquery    equ    0f5h            ; EBIOS get redirection info
  657. ebpresent equ    0f4h            ; EBIOS presence check
  658.  
  659. ebport    dw    0            ; EBIOS equivalent serial port 0..3
  660. ebcoms    db    0,0            ; adapter (port), path( 80h=network)
  661.     db    16 dup (0)        ; Call name (host)
  662.     db    16 dup (0)        ; Listen name (null)
  663.     db    16 dup (0)        ; local name (null = use lan adapter)
  664.     db    0            ; unique name (1 = group name)
  665. ebhlp    db    'Name of server port$'    
  666. ebmsg2    db    cr,lf,'?No server port name is known,'
  667.     db    ' reenter the command with a name.$'
  668. ebmsg3    db    cr,lf,'?Unable to contact that port. Error code=$'
  669. ebiostab db    4            ; EBIOS table of local port names
  670.     mkeyw    '1',1
  671.     mkeyw    '2',2
  672.     mkeyw    '3',3
  673.     mkeyw    '4',4
  674.  
  675. tcpadrst db    cr,lf,'  tcp/ip address: $'    ; TCP/IP status msgs
  676. tcpsubst db    cr,lf,'  tcp/ip subnetmask: $'
  677. tcpdomst db    cr,lf,'  tcp/ip domain: $'
  678. tcpgatest db    cr,lf,'  tcp/ip gateway: $'
  679. tcppnsst db    cr,lf,'  tcp/ip primary-nameserver: $'
  680. tcpsnsst db    cr,lf,'  tcp/ip secondary-nameserver: $'
  681. tcpbcstst db    cr,lf,'  tcp/ip broadcast: $'
  682. tcphostst db    cr,lf,'  tcp/ip host: $'
  683. tcphlp    db    cr,lf,'Internet name  machine.domain  or'
  684.     db    '  Internet address  nnn.nnn.nnn.nnn$'
  685. tcponptr dw    ktcpstart,seg _TEXT        ; far pointers to TCP start
  686. tcpoffptr dw    ktcpstop,seg _TEXT        ; and stop procedures
  687. data    ends
  688.  
  689. code    segment
  690.     extrn    comnd:near, prompt:near, dopar:near, lclyini:near, atsclr:near
  691.     extrn    strcpy:near, strlen:near,decout:near, prtasz:near, prtscr:near
  692.     extrn    kbsusp:near, kbrest:near        ; in msuibm.asm
  693.     extrn    strcat:near, valout:near, crun:near
  694.  
  695.     assume    cs:code, ds:data, es:nothing
  696.  
  697. fprtasz    proc    far
  698.     call    prtasz
  699.     ret
  700. fprtasz    endp
  701.  
  702. ; local initialization
  703.  
  704. lclini    proc    near
  705.     mov    flags.comflg,1    ; assume COM1 for communications port
  706.     call    model        ; get model of IBM machine
  707.     mov    lclsusp,offset suspend ; call this when suspending to DOS
  708.     mov    lclrest,offset restore ; call this when returning from DOS
  709.     mov    lclexit,offset finexit ; call this when exiting Kermit
  710.     call    getcodep        ; get Code Page ident
  711.     call    lclyini        ; let other modules initialize too...
  712.     ret
  713. lclini    endp
  714.  
  715. ; Call these routines when suspending Kermit to go to DOS
  716. suspend    proc    near
  717.     call    kbsusp        ; DEC LK250 keyboard, set back to DOS mode
  718.     cmp    flags.comflg,'t'; doing TCP?
  719.     je    suspen1        ; e = yes, don't touch port
  720.     call    ihosts        ; suspend the host
  721.     mov    ax,20        ; wait 20 millisec for port to finish
  722.     call    pcwait
  723.     call    serrst
  724. suspen1:ret
  725. suspend    endp
  726.  
  727. ; Call these routines when returning to Kermit from DOS
  728. restore    proc    near
  729.     call    getcodep    ; reset Code Page ident
  730.     call    kbrest        ; DEC LK250 keyboard, set back to DEC mode
  731.     cmp    flags.comflg,'t'; doing TCP?
  732.     je    restor1        ; e = yes, don't touch port
  733.     call    serini        ; reinit serial port
  734.     call    ihostr        ; resume the host
  735. restor1:ret
  736. restore    endp
  737.  
  738. ; Get the currently active Code Page ident into flags.chrset. User defined
  739. ; table overrides DOS report.
  740. getcodep proc    near
  741.     cmp    flags.chrset,1        ; user-defined table in use?
  742.     je    getcod1            ; e = yes
  743.     cmp    flags.chrset,866    ; forced CP866 in use?
  744.     je    getcod1            ; e = yes
  745.     mov    flags.chrset,437    ; find default global char set
  746.     cmp    dosnum,0300h+30        ; DOS version 3.30 or higher?
  747.     jb    getcod1            ; b = no, no Code Pages
  748.     mov    ax,6601h        ; get global Code Page
  749.     int    dos            ; bx=active Code Page, dx=boot CP
  750.     mov    flags.chrset,bx        ; setup default SET FILE CHAR SET
  751. getcod1:ret
  752. getcodep endp
  753.  
  754. ; Call these routines when doing final exit of Kermit
  755. finexit    proc    near
  756.     call    netclose    ; close network connections
  757.     call    kbsusp        ; DEC LK250 keyboard, set back to DOS mode
  758.     call    serrst        ; reset serial port
  759.     ret
  760. finexit    endp
  761.  
  762. ; The IBM PC's. If jr then redo IBM baud rate with jr's values.
  763. model    proc    near
  764.     mov    isps2,0            ; PS/2 present indicator
  765.     push    es
  766.     push    ax            ; get IBM model code at F000:FFFEh
  767.     mov    ax,0f000h        ; address ROM
  768.     mov    es,ax
  769.     mov    al,byte ptr es:[0fffeh]    ; get model id byte
  770.     cmp    al,0fdh            ; PC jr?
  771.     jne    modelx            ; ne = no
  772.     push    ds
  773.     pop    es            ; set es to data segment
  774.     mov    si,offset bddat        ; regular IBM baud rate table
  775.     mov    di,offset jrbddat    ; PCjr baud rate table
  776.     mov    cl,baudlen        ; number of words to copy
  777.     xor    ch,ch
  778.     cld
  779.     rep    movsw            ; copy PCjr values to IBM table
  780.     jmp    short modelx
  781.     mov    ah,0ch            ; AT and PS/2 configuration call
  782.     xor    al,al
  783.     int    15h            ; IBM Bios
  784.     jc    modelx            ; c = no information
  785.     cmp    word ptr es:[bx+2],040fch ; PS/2 model 50?
  786.     je    model3            ; e = yes
  787.     cmp    word ptr es:[bx+2],050fch ; PS/2 model 60?
  788.     je    model3            ; e = yes
  789.     cmp    byte ptr es:[bx+2],0f8h ; PS/2 model 80?
  790.     jne    modelx            ; ne = no
  791. model3:    mov    isps2,1            ; say real PS/2 for IRQ setting
  792. modelx:    pop    ax
  793.     pop    es
  794.     ret
  795. model    endp
  796.  
  797. ; show the definition of a key.  The terminal argument block (which contains
  798. ; the address and length of the definition tables) is passed in ax.
  799. ; Returns a string to print in AX, length of same in CX.
  800. ; Returns normally. Obsolete, name here for external reference only.
  801. showkey    proc    near
  802.     ret                ; return
  803. showkey    endp
  804. code    ends
  805.  
  806. code1    segment
  807.     assume    cs:code1
  808.  
  809. ftcpstats proc    far            ; TCP/IP status display
  810.     mov    ah,prstr
  811.     mov    dx,offset tcpadrst
  812.     int    dos
  813.     mov    dx,tcpdata[0]        ; offset of tcpaddress string
  814.     call    fprtasz
  815.     mov    dx,offset tcpsubst
  816.     int    dos
  817.     mov    dx,tcpdata[2]        ; offset of tcp subnetmask string
  818.     call    fprtasz
  819.     mov    dx,offset tcpdomst
  820.     int    dos
  821.     mov    dx,tcpdata[4]
  822.     call    fprtasz
  823.     mov    dx,offset tcpgatest
  824.     int    dos
  825.     mov    dx,tcpdata[6]
  826.     call    fprtasz
  827.     mov    dx,offset tcppnsst
  828.     int    dos
  829.     mov    dx,tcpdata[8]
  830.     call    fprtasz
  831.     mov    dx,offset tcpsnsst
  832.     int    dos
  833.     mov    dx,tcpdata[10]
  834.     call    fprtasz
  835.     mov    dx,offset tcpbcstst
  836.     int    dos
  837.     mov    dx,tcpdata[14]
  838.     call    fprtasz
  839.     mov    dx,offset tcphostst
  840.     int    dos
  841.     mov    dx,tcpdata[12]
  842.     call    fprtasz
  843.     ret
  844. ftcpstats endp
  845. code1    ends
  846.  
  847. code    segment
  848.     assume    cs:code
  849.  
  850. ; SHOW MODEM, displays current status of lines DSR, CD, and CTS.
  851. ; Uses byte mdmhand, the modem line status register.
  852. shomodem proc    near
  853.     mov    ah,cmeol        ; get a confirm
  854.     call    comnd
  855.     jnc    shomd1a            ; nc = success
  856.     ret
  857. shomd1a:mov    dx,offset msmsg7    ; no modem status for network
  858.     call    getmodem        ; get modem status
  859.     mov    mdmhand,al
  860.     mov    ah,prstr
  861.     mov    dx,offset msmsg1    ; modem ready msg
  862.     test    mdmhand,20h        ; is DSR asserted?
  863.     jz    shomd1            ; z = no
  864.     mov    dx,offset msmsg2    ; say not asserted
  865. shomd1:    int    dos
  866.     mov    dx,offset msmsg3    ; CD asserted msg
  867.     test    mdmhand,80h        ; CD asserted?
  868.     jz    shomd2            ; z = no
  869.     mov    dx,offset msmsg4    ; say not asserted
  870. shomd2:    int    dos
  871.     mov    dx,offset msmsg5    ; CTS asserted msg
  872.     test    mdmhand,10h        ; CTS asserted?
  873.     jz    shomd3            ; z = no
  874.     mov    dx,offset msmsg6    ; say not asserted
  875. shomd3:    mov    ah,prstr
  876.     int    dos
  877.     
  878.     mov    al,flags.comflg
  879.     cmp    al,'1'            ; UART?
  880.     jae    shomd3c            ; ae = no
  881.     add    al,'0'            ; COMnumber
  882.     mov    msmsg8+7,al        ; stuff in msg
  883.     mov    ah,prstr
  884.     mov    dx,offset msmsg8    ; show port base address
  885.     int    dos
  886.     mov    ax,modem.mddat        ; port address
  887.     mov    cx,16            ; in hex
  888.     call    valout
  889.     mov    ah,prstr
  890.     mov    dx,offset msmsg9    ; and IRQ
  891.     int    dos
  892.     mov    ax,modem.mdintv        ; interrupt vector
  893.     mov    cl,al
  894.     and    ax,7            ; lower three bits of IRQ
  895.     cmp    cl,60h            ; using cascaded 8259?
  896.     jb    shomd3a            ; b = no
  897.     add    ax,8            ; say IRQ 8..15
  898. shomd3a:call    decout            ; output as decimal
  899.  
  900. shomd3c:call    ftcpstats        ; call TCP/IP FAR worker
  901.     mov    dx,offset netmsg3    ; local name
  902.     int    dos
  903.     mov    cx,16
  904.     mov    di,offset deflname    ; default Netbios name
  905.     call    prtscr
  906.     cmp    rcv.scb_lname,' '    ; have NetBios name yet?
  907.     jbe    shomd4            ; be = no, skip this part
  908.     mov    ah,prstr
  909.     mov    dx,offset netmsg4    ; remote name
  910.     int    dos
  911.     mov    cx,16
  912.     mov    di,offset rcv.scb_rname
  913.     call    prtscr
  914. shomd4:    cmp    latservice,0        ; DECnet name available?
  915.     je    shomd5            ; e = no
  916.     mov    ah,prstr
  917.     mov    dx,offset netmsg5
  918.     int    dos
  919.     mov    dx,offset latservice    ; network host name, asciiz
  920.     call    prtasz
  921. shomd5:    cmp    word ptr internet,0    ; have TELAPI Internet address?
  922.     je    shomd7            ; e = no
  923.     mov    ah,prstr
  924.     mov    dx,offset netmsg6
  925.     int    dos
  926.     xor    bx,bx            ; subscript
  927.     mov    cx,4            ; four fields
  928. shomd6:    mov    al,internet[bx]        ; binary internet address
  929.     xor    ah,ah
  930.     call    decout
  931.     cmp    cx,1            ; doing last field?
  932.     je    shmod6a            ; e = yes, no dot
  933.     mov    dl,'.'
  934.     mov    ah,conout
  935.     int    dos
  936. shmod6a:inc    bx
  937.     loop    shomd6
  938. shomd7:    cmp    tesname,0        ; have TES name?
  939.     je    shomd8            ; e = no
  940.     mov    ah,prstr
  941.     mov    dx,offset netmsg7
  942.     int    dos
  943.     mov    dx,offset tesname    ; node name
  944.     call    prtasz            ; show, asciiz
  945.     clc
  946.     ret
  947. shomd8:    cmp    ebcoms+2,0        ; have an EBIOS name?
  948.     je    shomd9            ; e = no
  949.     mov    ah,prstr
  950.     mov    dx,offset netmsg8
  951.     int    dos
  952.     mov    cx,16
  953.     mov    di,offset ebcoms+2    ; host port, 16 chars space filled
  954.     call    prtscr
  955. shomd9:    clc
  956.     ret
  957. shomodem endp
  958.  
  959. ; Get modem status and set global byte mdmhand. Preserve all registers.
  960. getmodem proc    near            ; gets modem status upon request
  961.     cmp    portin,1        ; port active?
  962.     je    getmod1            ; e = yes
  963.     mov    bl,flags.comflg        ; pass current port ident
  964.     cmp    bl,'4'            ; above UART and Bios?
  965.     ja    getmod1            ; a = yes, do not start the port
  966.     call    comstrt            ; do SET PORT command now
  967.     jnc    getmod1            ; nc = success
  968.     ret                ; failed to set port
  969. getmod1:xor    al,al            ; assume nothing is on
  970.     cmp    flags.comflg,'1'    ; UART?
  971.     jae    getmod2            ; ae = no
  972.     cmp    flags.comflg,0        ; null port?
  973.     je    getmodx            ; e = yes, no status
  974.     mov    dx,modem.mdstat        ; hardware, line status reg
  975.     inc    dx            ; modem status reg
  976.     in    al,dx
  977.     jmp    short getmodx
  978. getmod2:cmp    flags.comflg,'4'    ; above Bios? (networks)
  979.     ja    getmod3            ; a = yes, no status
  980.     mov    ah,3            ; ask Bios for modem status into al
  981.     push    dx
  982.     mov    dl,flags.comflg        ; get port id
  983.     sub    dl,'1'            ; remove ascii bias (BIOS1 -> 0)
  984.     int    rs232
  985.     pop    dx
  986. getmod3:cmp    flags.comflg,'E'    ; IBM EBIOS?
  987.     jne    getmodx            ; ne = no
  988.     mov    ah,3            ; get Bios style modem status
  989.     push    dx
  990.     mov    dx,ebport        ; current EBIOS port
  991.     int    rs232
  992.     pop    dx
  993. getmodx:xor    ah,ah            ; return status in al
  994.     clc
  995.     ret
  996. getmodem endp
  997.  
  998. ; Clear the input buffer. This throws away all the characters in the
  999. ; serial interrupt buffer.  This is particularly important when
  1000. ; talking to servers, since NAKs can accumulate in the buffer.
  1001. ; Returns normally.
  1002.  
  1003. CLRBUF    PROC    NEAR
  1004.     cli
  1005.     mov    srcpnt,offset source    ; receive circular buffer
  1006.     mov    count,0            ; receive circular buffer
  1007.     sti
  1008.     call    prtchr            ; empty any intermediate (net) buffers
  1009.     cli
  1010.     mov    srcpnt,offset source    ; receive circular buffer
  1011.     mov    count,0            ; receive circular buffer
  1012.     mov    xmtcnt,0        ; network output buffer count
  1013.     sti
  1014.     clc
  1015.     cmp    flags.comflg,'E'    ; using EBIOS?
  1016.     jne    clrbuf3            ; ne = no
  1017.     mov    dx,ebport        ; port 0..3
  1018. clrbuf1:mov    ax,ebbufcnt*256+2    ; see if rcvr buffer has chars already
  1019.     int    rs232
  1020.     jcxz    clrbuf3            ; z = no, ok to reset buffering
  1021.     mov    ah,ebrcv        ; do receive /nowait to clear buff
  1022.     int    rs232
  1023.     jmp    short clrbuf1        ; repeat til empty
  1024. clrbuf3:ret
  1025. CLRBUF    ENDP
  1026.  
  1027. ; Clear to the end of the current line.  Returns normally.
  1028. ; Upgraded for Topview compatibility.
  1029. CLEARL    PROC    NEAR
  1030.     push    ax
  1031.     push    bx
  1032.     push    dx
  1033.     mov    ah,3            ; Clear to end of line
  1034.     xor    bh,bh
  1035.     int    video            ; Get current cursor position into dx
  1036.     mov    ax,dx            ; Topview compatible clear line
  1037.     mov    bh,ah            ; same row
  1038.     mov    bl,byte ptr low_rgt    ; last column
  1039.     call    atsclr            ; clear from ax to bx, screen coord
  1040.     pop    dx
  1041.     pop    bx
  1042.     pop    ax
  1043.     ret
  1044. CLEARL    ENDP
  1045.  
  1046. ; This routine blanks the screen.  Returns normally.
  1047. ; Upgraded to Topview compatiblity.
  1048. CMBLNK    PROC    NEAR
  1049.     push    ax
  1050.     push    bx
  1051.     xor    ax,ax            ; from screen loc 0,0
  1052.     mov    bx,low_rgt    ; to end of text screen (lower right corner)
  1053.     inc    bh            ; include status line
  1054.     call    atsclr             ; do Topview compatible clear, in msyibm
  1055.     pop    bx
  1056.     pop    ax
  1057.     ret
  1058. CMBLNK  ENDP
  1059.  
  1060. ; Locate: homes the cursor.  Returns normally.
  1061.  
  1062. LOCATE  PROC    NEAR
  1063.     xor    dx,dx            ; Go to top left corner of screen
  1064.     jmp    poscur
  1065. LOCATE  ENDP
  1066.  
  1067. ; Position the cursor according to contents of DX:
  1068. ; DH contains row, DL contains column.  Returns normally.
  1069. POSCUR    PROC    NEAR
  1070.     push    ax
  1071.     push    bx
  1072.     mov    ah,2            ; Position cursor
  1073.     xor    bh,bh            ; page 0
  1074.     int    video
  1075.     pop    bx
  1076.     pop    ax
  1077.     ret
  1078. POSCUR    ENDP
  1079.  
  1080. ; Delete a character from the screen.  This works by printing
  1081. ; backspaces and spaces.
  1082.  
  1083. DODEL    PROC    NEAR
  1084.     mov    ah,prstr
  1085.     mov    dx,offset delstr    ; Erase character
  1086.     int    dos            
  1087.     ret
  1088. DODEL    ENDP
  1089.  
  1090. ; Move the cursor to the left margin, then clear to end of line.
  1091.  
  1092. CTLU    PROC    NEAR
  1093.     mov    ah,prstr
  1094.     mov    dx,offset clrlin
  1095.     int    dos
  1096.     jmp    clearl
  1097. CTLU    ENDP
  1098.  
  1099.  
  1100. BEEP    PROC    NEAR
  1101.     mov    timeract,1    ; say timer chip is being used here
  1102.     push    ax
  1103.     push    cx
  1104.     mov    al,10110110B    ; Gen a short beep (long one losses data.)
  1105.     out    timercmd,al    ; set Timer to to mode 3
  1106.     mov    ax,1512        ; divisor, for frequency
  1107.     out    timer2data,al    ; send low byte first
  1108.     mov    al,ah
  1109.     out    timer2data,al
  1110.     in    al,ppi_port    ; get 8255 Port B setting
  1111.     or    al,3        ; turn on speaker and timer
  1112.     out    ppi_port,al    ; start speaker and timer
  1113.     push    ax
  1114.     mov    ax,40        ; 40 millisecond beep, calibrated time
  1115.     call    pcwait
  1116.     pop    ax
  1117.     in    al,ppi_port
  1118.     and    al,0fch        ; turn off speaker and timer
  1119.     out    ppi_port,al
  1120.     pop    cx
  1121.     pop    ax
  1122.     mov    timeract,0    ; say timer chip is no longer in use here
  1123.     clc
  1124.     ret
  1125. BEEP    ENDP 
  1126.  
  1127. ; write a line in inverse video at the bottom of the screen...
  1128. ; the line is passed in dx, terminated by a $.  Returns normally.
  1129. putmod    proc    near
  1130.     push    ax        ; save regs
  1131.     push    bx
  1132.     push    cx
  1133.     push    si
  1134.     push    dx        ; preserve message
  1135.     mov    bl,scbattr    ; screen attributes at Kermit init time
  1136.     and    bl,77h        ; get colors, omit bright and blink
  1137.     rol    bl,1        ; interchange fore and background
  1138.     rol    bl,1
  1139.     rol    bl,1
  1140.     rol    bl,1
  1141.     xor    bh,bh        ; preset page 0
  1142.     mov    temp,bx        ; temp = page 0, reverse video 
  1143.     mov    dx,low_rgt    ; ending location is lower right corner
  1144.     inc    dh        ;  of status line
  1145.     mov    cx,dx        ; start is status left side
  1146.     xor    cl,cl        ; left side
  1147.     mov    ax,600h        ; scroll to clear the line
  1148.     mov    bh,byte ptr temp ; set inverse video attributes
  1149.     int    video
  1150.     mov    dx,low_rgt    ; last text line
  1151.     inc    dh        ; status line
  1152.     xor    dl,dl        ; left side
  1153.     call    poscur
  1154.     pop    si        ; get message back
  1155.     mov    cx,1        ; only one char at a time
  1156.     xor    bh,bh        ; page 0
  1157.     cld
  1158. putmo1:    lodsb            ; get a byte
  1159.     cmp    al,'$'        ; end of string?
  1160.     je    putmo2
  1161.     push    si        ; save si
  1162.     push    ax        ; and the char
  1163.     call    poscur
  1164.     inc    dl        ; increment for next write
  1165.     pop    ax        ; recover char
  1166.     mov    ah,9        ; try this
  1167.     mov    bx,temp        ; page 0, inverse video
  1168.     int    video
  1169.     pop    si        ; recover pointer
  1170.     cmp    dl,crt_cols    ; beyond physical right border?
  1171.     jb    putmo1        ; b = no
  1172. putmo2:    pop    si
  1173.     pop    cx
  1174.     pop    bx
  1175.     pop    ax
  1176.     ret
  1177. putmod    endp
  1178.  
  1179. ; clear the mode line written by putmod.
  1180. clrmod    proc    near
  1181.     push    ax        ; save regs
  1182.     push    bx
  1183.     push    cx
  1184.     push    dx
  1185.     mov    ax,600h        ; do a scroll up
  1186.     mov    dx,low_rgt    ; ending location is lower right corner
  1187.     inc    dh        ;  of status line
  1188.     mov    cx,dx        ; start is status left side
  1189.     xor    cl,cl        ; left side
  1190.     mov    bh,scbattr    ; use screen attributes at Kermit init time
  1191.     int    video
  1192.     pop    dx
  1193.     pop    cx
  1194.     pop    bx
  1195.     pop    ax
  1196.     ret
  1197. clrmod    endp
  1198.  
  1199. ; put a help message on the screen.  This one uses reverse video...
  1200. ; pass the message in ax, terminated by a null.
  1201. puthlp    proc    near
  1202.     push    bx        ; save regs
  1203.     push    cx
  1204.     push    dx
  1205.     push    si
  1206.     push    ax        ; preserve this
  1207.     cld
  1208.     mov    bl,scbattr    ; screen attributes at Kermit init time
  1209.     and    bl,77h        ; get colors, omit bright and blink
  1210.     rol    bl,1        ; interchange fore and background
  1211.     rol    bl,1
  1212.     rol    bl,1
  1213.     rol    bl,1
  1214.     xor    bh,bh        ; preset page 0
  1215.     mov    temp,bx        ; temp = page 0, reverse video 
  1216.  
  1217.     mov    si,ax        ; point to it
  1218.     mov    dh,1        ; init counter
  1219. puthl1:    lodsb            ; get a byte
  1220.     cmp    al,lf        ; linefeed?
  1221.     jne    puthl2        ; no, keep going
  1222.     inc    dh        ; count it
  1223.     jmp    short puthl1    ; and keep looping
  1224. puthl2:    or    al,al        ; end of string?
  1225.     jnz    puthl1        ; nz = no, keep going
  1226.     mov    ax,600h        ; scroll to clear window
  1227.     xor    cx,cx        ; from top left
  1228.     mov    dl,4fh        ; to bottom right of needed piece
  1229.     mov    bh,70h        ; inverse video
  1230.     mov    bh,bl        ; inverse video
  1231.     int    video
  1232.     call    locate        ; home cursor
  1233.     mov    bx,0070h    ; bh = page 0, bl = inverse video
  1234.     mov    bx,temp
  1235.     mov    cx,1        ; one char at a time
  1236.     cld            ; scan direction is forward
  1237.     pop    si        ; point to string again
  1238. puthl3:    lodsb            ; get a byte
  1239.     or    al,al        ; end of string?
  1240.     jz    puthl4        ; z = yes, stop
  1241.     push    si        ; save around bios call
  1242.     cmp    al,' '        ; printable?
  1243.     jb    puth21        ; b = no
  1244.     mov    ah,9        ; write char at current cursor position
  1245.     int    video        ; do the Bios int 10h call
  1246.     inc    dl        ; point to next column
  1247.     jmp    short puth23    ; move cursor there
  1248. puth21:    cmp    al,cr        ; carriage return?
  1249.     jne    puth22        ; ne = no
  1250.     xor    dl,dl        ; set to column zero
  1251.     jmp    short puth23
  1252. puth22:    cmp    al,lf        ; line feed?
  1253.     jne    puth23
  1254.     inc    dh        ; go to next line
  1255. puth23:    mov    ah,2        ; set cursor position to dx
  1256.     int    video
  1257.     pop    si        ; restore pointer
  1258.     jmp    short puthl3    ; and keep going
  1259. puthl4:    mov    dh,byte ptr low_rgt+1    ; go to last line
  1260.     inc    dh
  1261.     xor    dl,dl
  1262.     call    poscur        ; position cursor
  1263.     pop    si
  1264.     pop    dx
  1265.     pop    cx
  1266.     pop    bx
  1267.     ret
  1268. puthlp    endp
  1269.  
  1270. ; Compute number of iterations needed in procedure pcwait inner loop
  1271. ; to do one millisecond delay increments. Uses Intel 8253/8254 timer chip
  1272. ; (timer #2) to measure elapsed time assuming 1.193182 MHz clock.
  1273. ; Called by serini below. For IBM PC compatible machines.
  1274. ; Regs preserved. 16 April 87 and 4 July 1991 [jrd]
  1275. pcwtst    proc    near
  1276.     push    cx
  1277.     mov    cx,5        ; number of tests to perform
  1278. pcwtst1:call    pcwtst2        ; do the test and new pcwcnt calculation
  1279.     loop    pcwtst1        ; repeat several times for convergence
  1280.     pop    cx
  1281.     ret
  1282.  
  1283. pcwtst2:push    ax
  1284.     push    bx
  1285.     push    cx
  1286.     push    dx
  1287.     in    al,ppi_port    ; 8255 chip port B, 61h
  1288.     and    al,0fch        ; speaker off (bit 1), stop timer (bit 0)
  1289.     out    ppi_port,al    ; do it
  1290.   ; 10 = timer 2, 11 = load low byte then high byte, 010 = mode 2, 0 = binary
  1291.     mov    al,10110100B    ; command byte
  1292.     out    timercmd,al    ; timer command port, 43h
  1293.     xor    al,al        ; clear initial count for count-down
  1294.     out    timer2data,al    ; low order byte of count preset, to port 42h
  1295.     out    timer2data,al    ; high order byte, to the same place
  1296.     in    al,ppi_port    ; get 8255 setting
  1297.     mov    dl,al        ; remember it in dl
  1298.     and    al,0fch        ; clear our control bits
  1299.     or    al,1           ; start counter now (Gate = 1, speaker is off)
  1300.     out    ppi_port,al    ; do it, OUT goes low
  1301.                 ; this is the test loop
  1302.     mov    ax,8        ; wait 8 millisec
  1303.     call    pcwait        ; call the software timer
  1304.                 ; end test loop
  1305.     mov    al,dl        ; restore ppi port, stop timer
  1306.     out    ppi_port,al
  1307.     in    al,timer2data    ; read count down value
  1308.     xchg    al,ah        ; save low order byte
  1309.     in    al,timer2data    ; get high order byte
  1310.     xchg    ah,al        ; put in correct sequence
  1311.     neg    ax        ; subtract from zero to get elapsed tics
  1312.     mov    bx,ax        ; save observed tics
  1313.     mov    ax,pcwcnt    ; current pcwcnt value
  1314.     ; new pcwcnt= old pcwcnt * [1193(tics/ms) / (observed tics / loops)]
  1315.     mov    cx,8*1193
  1316.     mul    cx    
  1317.     or    bx,bx        ; zero observed tics?
  1318.     jz    pcwtst3        ; z = yes, divide by one
  1319.     div    bx        ; divided by observed tics
  1320. pcwtst3:mov    pcwcnt,ax    ; store quotient as new inner loop counter
  1321.     pop    dx
  1322.     pop    cx
  1323.     pop    bx
  1324.     pop    ax
  1325.     ret
  1326. pcwtst    endp
  1327.     
  1328. ;; Wait for the # of milliseconds in ax, for non-IBM compatibles.
  1329. ;; Thanks to Bernie Eiben for this one. Modified to use adjustable 
  1330. ; inner loop counter (pcwcnt, adjusted by proc pcwtst) by [jrd].
  1331. pcwait    proc    near
  1332.     push    cx
  1333. pcwai0:    mov    cx,pcwcnt    ; inner loop counter for 1 ms (240 @ 4.77 MHz)
  1334. pcwai1:    sub    cx,1        ; inner loop takes 20 clock cycles
  1335.     jnz    pcwai1
  1336.     dec    ax        ; outer loop counter
  1337.     jnz    pcwai0        ; wait another millisecond
  1338.     pop    cx
  1339.     ret
  1340. pcwait    endp
  1341.  
  1342. ; set the current port.  
  1343. ; Note: serial port addresses are found by looking in memory at 40:00h and
  1344. ; following three words for COM1..4, resp. All UARTS are assumed to follow
  1345. ; std IBM addresses relative to 03f8h for COM1, and actual address are offset
  1346. ; from value found in segment 40h. Global byte flags.comflg is 1,2,3,4 for
  1347. ; COM1..4, and is 'N' for NetBios, etc.
  1348. ; 'O' is for Intel Opennet Network (FGR)
  1349. ; If address 02f8h is found in 40:00h then name COM1 is retained but COM2
  1350. ;  addressing is used to access the UART and a notice is displayed. IRQ 3
  1351. ; or IRQ 4 is sensed automatically for any COMx port.
  1352. COMS    PROC    NEAR
  1353.     mov    dx,offset comptab    ; table of legal comms ports
  1354.     xor    bx,bx            ; no extra help text
  1355.     mov    ah,cmkey        ; parse key word
  1356.     call    comnd
  1357.     jnc    coms0a            ; nc = success
  1358.     ret                ; failure
  1359. coms0a:    cmp    bl,'4'            ; networks?
  1360.     ja    comstrt            ; a = yes
  1361.     mov    ah,cmeol        ; non-network
  1362.     push    bx
  1363.     call    comnd            ; get a confirm
  1364.     pop    bx
  1365.     jnc    comstrt            ; nc = success
  1366.     ret                ; failure
  1367.  
  1368. COMSTRT:mov    temp,bx            ; port ident is in BL
  1369.     cmp    bl,'N'            ; NetBios network?
  1370.     jne    comst2a            ; ne = no
  1371.       jmp    comsn            ; yes, get another item for networks
  1372. comst2a:cmp    bl,'O'            ; Opennet network?
  1373.       jne    comst2                  ; ne = no
  1374.     jmp    comso            ; yes, get another item for networks
  1375. comst2:    cmp    bl,'U'            ; Ungermann Bass net?
  1376.     jne    comst3            ; ne = no
  1377.     jmp    comsub
  1378. comst3:    cmp    bl,'D'            ; DECnet?
  1379.     jne    comst4            ; ne = no
  1380.     jmp    comsd            ; do DECnet startup
  1381. comst4:    cmp    bl,'E'            ; IBM EBIOS?
  1382.     jne    comst4a            ; ne = no
  1383.     jmp    comse            ; do EBIOS checkup
  1384. comst4a:cmp    bl,'W'            ; Novell NASI?
  1385.     jne    comst5            ; ne = no
  1386.     jmp    comsub
  1387. comst5:    cmp    bl,'C'            ; 3Com BAPI?
  1388.     jne    comst5a            ; ne = no
  1389.     jmp    comsbapi
  1390. comst5a:cmp    bl,'T'            ; Novell TELAPI
  1391.     jne    comst5b            ; ne = no
  1392.     jmp    comstelapi
  1393. comst5b:cmp    bl,'I'            ; TES?
  1394.     jne    comst5b1        ; ne = no
  1395.     jmp    comstes
  1396. comst5b1:cmp    bl,'t'            ; Telnet, internal?
  1397.     jne    comst5c            ; ne = no
  1398.     jmp    comstn
  1399. comst5c:cmp    flags.comflg,'N'    ; have been running on NetBios?
  1400.      je    coms1c            ; e = yes
  1401.     cmp    flags.comflg,'E'    ; how about EBIOS?
  1402.     je    coms1c            ; e = yes
  1403.      cmp    flags.comflg,'O'    ; have been running on Opennet?
  1404.      jne    coms2            ; ne = no
  1405.                       ; stop sources of NetBios interrupts
  1406. coms1c:    mov    bx,offset can        ; cancel outstanding requests
  1407.     mov    can.scb_cmd,ncancel    ; set cancel op code
  1408.     cmp    lposted,1        ; listen outstanding?
  1409.     jne    coms1a            ; ne = no
  1410.     mov    can.scb_baddr,offset lsn ; cancel listen
  1411.     call    session
  1412.     mov    lposted,0
  1413. coms1a:    cmp    rposted,1        ; receive outstanding?
  1414.     mov    rposted,0        ; clear interlock flag no matter what
  1415.     jne    coms2            ; ne = no
  1416.     mov    can.scb_baddr,offset rcv ; cancel receive
  1417.     call    session
  1418.     
  1419. coms2:    call    serrst            ; close current comms port
  1420.     mov    al,byte ptr temp    ; get COMx (1-4)
  1421.     mov    flags.comflg,al        ; remember port ident
  1422.     cmp    al,'1'            ; Bios?
  1423.     jb    coms2a            ; b = no, hardware
  1424.     sub    al,'0'            ; remove ascii bias for portinfo
  1425. coms2a:    dec    al
  1426.     xor    ah,ah            ; count ports from 0
  1427.     push    bx            ; set port structure
  1428.     mov    bx,type prtinfo        ; size of each portinfo structure
  1429.     mul    bl            ; times port number
  1430.     pop    bx            ; restore register
  1431.     add    ax,offset port1        ; plus start of COM1
  1432.     mov    portval,ax        ; points to our current port struct
  1433.     cmp    flags.comflg,'1'    ; Bios path?
  1434.     jb    coms4            ; b = no, check hardware
  1435.     add    ax,offset portb1-offset port1 ; correct to use Bios ports
  1436.     mov    portval,ax
  1437.     clc
  1438.     ret
  1439.  
  1440. coms4:     cmp    portin,-1        ; serial port touched yet?
  1441.     jne    coms4a            ; ne = yes, else avoid init looping
  1442.     mov    portin,0        ; say serial port is being touched
  1443. coms4a:    push    bx            ; save register
  1444.     push    es
  1445.     mov    ax,40h        ; look at RS232_base [bx] in Bios area 40:00h
  1446.     mov    es,ax
  1447.     mov    bx,temp            ; get desired port
  1448.     xor    bh,bh
  1449.     dec    bl            ; count com1 as bl = 0, etc
  1450.     shl    bx,1            ; make bx a word index
  1451.     mov    ax,es:[bx]        ; get modem base address into ax
  1452.     pop    es
  1453.     pop    bx
  1454.     or    ax,ax            ; is address zero?
  1455.     je    comsnh            ; e = yes, no serial port hardware
  1456. comsc:                    ; hardware tests
  1457.     mov    modem.mddat,ax    ; set base address (also data address) 03f8h
  1458.     add    ax,2
  1459.     mov    modem.mdiir,ax        ; interrupt identification reg 03fah
  1460.     inc    ax            ; increment to command port 03fbh
  1461.     mov    modem.mdcom,ax        ; set line control register address
  1462.     add    ax,2            ; increment to status port 03fdh
  1463.     mov    modem.mdstat,ax        ; set line-status port address
  1464.     call    chkport            ; get type of UART support
  1465.     jc    comsnu            ; c = not a real 8250 class UART
  1466.     call    chkint            ; find IRQ for the port
  1467.     jc    comsnu            ; c = not found, an error condition
  1468.     ret                ; success
  1469.  
  1470. comsnh:    mov    ah,prstr        ; no port address for hardware
  1471.     mov    dx,offset badprt
  1472.     int    dos
  1473.                     ; no port address or no UART or no IRQ
  1474. comsnu:    mov     ah,prstr        ; tell user about Bios pathway
  1475.     mov    dx,offset biosmsg
  1476.     int    dos
  1477.     mov    dl,byte ptr temp    ; selected hardware port
  1478.     add    dl,'0'            ; map to Bios
  1479.     mov    flags.comflg,dl
  1480.     mov    ah,conout        ; say port number
  1481.     int    dos
  1482.     stc                ; say error
  1483.     ret
  1484.                                         ; Opennet Network support (FGR)
  1485. comso:    mov    inettyp,'O'        ; remember OpenNet type network
  1486.     jmp    short comso2        ; do generic network code
  1487.                       ; NetBios Network support
  1488. comsn:    mov    inettyp,'N'        ; remember Netbios type network
  1489. comso2:    mov    ah,cmword        ; get a word (remote node name)
  1490.     mov    dx,offset decbuf    ; work buffer
  1491.     mov    word ptr decbuf,0    ; insert terminator
  1492.     mov    bx,offset nethlp    ; help message
  1493.     call    comnd            ; get the name, ignore errors
  1494.     mov    newnambuf,al        ; save number of chars entered
  1495.     mov    ah,cmeol
  1496.     call    comnd            ; get a confirm
  1497.     jc    comsn2            ; c = failure
  1498.     call    serrst            ; reset serial port
  1499.     cmp    newnambuf,0        ; any name given?
  1500.     je    comsn1            ; e = no, use current name
  1501.     mov    si,offset decbuf
  1502.     mov    di,offset nambuf    ; copy to here
  1503.     call    strcpy
  1504. comsn1:    call    chknet            ; start network usage
  1505.     jc    comsn2            ; c = failed
  1506.     cmp    pcnet,0            ; is network alive (non-zero)?
  1507.     jne    comsn4            ; ne = yes
  1508. comsn2:    stc
  1509.     ret                ; failure
  1510.  
  1511. comsn4:    mov    portval,offset portn     ; set Network port structure address
  1512.     mov    portn.portrdy,1        ; say the comms port is ready
  1513.     mov    al,inettyp        ; FGR - get saved network type
  1514.     mov    flags.comflg,al        ; Set the Netbios port flag
  1515.     call    chkport            ; set type of port support
  1516.     clc                ; return success
  1517.     ret                ; End NetBios
  1518.  
  1519.                     ; Ungermann-Bass terminal port [ohl +]
  1520. comsub:    push    bx            ; save net type U or W
  1521.     mov     ah,cmeol
  1522.         call    comnd                   ; get a confirm
  1523.     jc    comsub0            ; c = failure
  1524.     call    serrst            ; reset serial port
  1525.         call    chkub                   ; check UB network presence
  1526.     pop    bx            ; recover net type U or W
  1527.     jnc    comsub1            ; nc = present
  1528. comsub0:ret                ; return failure
  1529.  
  1530. comsub1:mov     portval,offset portn ; set Network port data structure address
  1531.     mov    portn.portrdy,1        ; say the comms port is ready
  1532.         mov     flags.comflg,bl        ; set the comm port flag
  1533.     mov     pcnet,2                 ; network is present and active
  1534.         clc                ; return success
  1535.         ret                ; End Ungermann Bass / Novell NASI
  1536.  
  1537.                     ; DECnet
  1538. comsd:    mov    ah,cmword        ; get a word (remote node name)
  1539.     mov    dx,offset decbuf    ; work buffer
  1540.     mov    word ptr decbuf,0    ; insert terminator
  1541.     mov    bx,offset dnethlp    ; help message
  1542.     call    comnd            ; get the name
  1543.     mov    temp,ax            ; save number of chars entered
  1544.     mov    ah,cmword        ; get optional LAT service name
  1545.     mov    dx,offset decbuf+80    ; work near end of this buffer
  1546.     mov    word ptr decbuf+80,0    ; insert terminator
  1547.     mov    bx,offset nethlp2    ; help message
  1548.     mov    comand.cmblen,16    ; length of buffer (password = 16 chr)
  1549.     call    comnd            ; get the name, ignore if absent
  1550.     mov    decbuf+79,al        ; store byte count in name here
  1551.     mov    comand.cmblen,0        ; length of buffer back to normal
  1552.     mov    ah,cmeol
  1553.     call    comnd            ; get a confirm
  1554.     jnc    comsd3
  1555.     ret                ; did not get a confirm
  1556. comsd3:    cmp    temp,0            ; any node name?
  1557.     je    comsd8            ; e = no, assume preestablished
  1558.      cmp    decbuf,'*'        ; just show LAT names?
  1559.     jne    comsd4            ; ne = no
  1560.     call    chkdec            ; see if network is available
  1561.     jc    comsd3a            ; c = no, no net available
  1562.     and    nettype,not decnet    ; remove CTERM indicator
  1563.     test    nettype,declat        ; LAT type present?
  1564.     jz    comsd3a            ; z = no
  1565.     call    latlst            ; show LAT names
  1566.     and    nettype,not declat    ; remove this indicator
  1567.     clc                ; success but do not make connection
  1568.     ret
  1569.  
  1570. comsd3a:mov    ah,prstr
  1571.     mov    dx,offset nonetmsg    ; say net is not available
  1572.     int    dos
  1573.     clc
  1574.     ret
  1575.                     ; put name in uppercase, strip '::'
  1576. comsd4:    mov    si,offset decbuf    ; the node name, make upper case
  1577.     mov    cx,temp            ; length of node name
  1578.     add    si,cx            ; and add '::' if absent
  1579.     cmp    byte ptr [si-1],':'    ; ended on colon?
  1580.     jne    comsd5            ; ne = no
  1581.     dec    cx            ; remove it
  1582.     cmp    byte ptr [si-2],':'    ; first colon present?
  1583.     jne    comsd5            ; e = yes
  1584.     dec    cx            ; remove it
  1585. comsd5:    mov    si,offset decbuf    ; uppercase and copy name
  1586.     mov    di,offset latservice    ; to this structure
  1587.     jcxz    comsd7a            ; z = empty name
  1588.     cld
  1589. comsd6:    lodsb                ; si = new node name
  1590.     cmp    al,'a'            ; in lower case?
  1591.     jb    comsd7            ; b = no
  1592.     cmp    al,'z'            ; in lower case?
  1593.     ja    comsd7            ; a = no
  1594.     and    al,not 20h        ; convert to upper case
  1595. comsd7:    stosb
  1596.     loop    comsd6
  1597. comsd7a:mov    byte ptr [di],0        ; terminate latservice name
  1598.     mov    si,offset decbuf+80    ; LAT password
  1599.     mov    di,offset latpwd    ; where it will reside
  1600.     mov    byte ptr [di],0        ; clear password now
  1601.     call    strcpy            ; copy it, asciiz
  1602.     mov    cl,decbuf+79        ; length of name
  1603.     xor    ch,ch
  1604.     add    di,cx            ; point to trailer
  1605.     sub    cx,16            ; max chars in password
  1606.     jle    comsd8            ; le = filled now, or no password
  1607.     mov    al,' '            ; make it space filled
  1608.     push    ds
  1609.     pop    es
  1610.     rep    stosb            ; fill in spaces
  1611. comsd8:    call    chkdec            ; see if network is available
  1612.     jnc    comsd9            ; nc = yes, it is
  1613.     mov    ah,prstr
  1614.     mov    dx,offset nonetmsg    ; say net is not available
  1615.     int    dos
  1616.     stc
  1617.     ret
  1618. comsd9:    mov    ah,prstr
  1619.     test    nettype,decnet        ; starting CTERM?
  1620.     jz    comsd9a            ; z = no
  1621.     mov    dx,offset decmsg4    ; assume CTERM
  1622.     int    dos
  1623. comsd9a:test    nettype,declat        ; LAT too?
  1624.     jz    comsd9b            ; z = no
  1625.     mov    dx,offset decmsg5    ; say LAT connection is ready
  1626.     int    dos
  1627. comsd9b:cmp    pcnet,2            ; session active?
  1628.     jb    comsd10            ; b = no, start a new one
  1629.     call    chknew            ; session exists, Resume or start new?
  1630.     jc    comsd11            ; c = resume
  1631.     call    nethangup        ; hangup current session
  1632. comsd10:call    serrst            ; reset serial port
  1633.     mov     portval,offset portn ; set Network port data structure address
  1634.     mov    flags.comflg,'D'    ; set the comm port flag
  1635.     mov    portin,0        ; say have tested a port
  1636.     mov    portn.portrdy,0        ; say the comms port is not ready yet
  1637. comsd11:clc
  1638.     ret                ; end of DECnet
  1639.  
  1640.  
  1641. comsbapi:mov    ah,bapihere        ; 3Com BAPI presence check
  1642.     xor    al,al
  1643.     mov    bx,0aaaah        ; undocumented magic
  1644.     int    bapiint
  1645.     cmp    ax,0af01h        ; signature
  1646.     jne    comsbap1        ; ne = not present
  1647.     call    serrst            ; close current port
  1648.     mov    ah,bapieecm        ; disable Enter Command Mode char
  1649.     xor    al,al
  1650.     int    bapiint
  1651.     mov    portval,offset portn ; set Network port data structure address
  1652.     mov    portn.portrdy,1        ; say the comms port is ready
  1653.     or    nettype,bapi        ; indentify network type
  1654.         mov     flags.comflg,'C'    ; set the comm port flag
  1655.     mov     pcnet,2            ; network is present and active
  1656.     clc                ; success
  1657.     ret
  1658. comsbap1:mov    ah,prstr
  1659.     mov    dx,offset nonetmsg    ; say no network
  1660.     int    dos
  1661. comsbap3:stc                ; say failure
  1662.     ret                ; end 3Com BAPI
  1663.  
  1664. comse:    mov    dx,offset ebiostab    ; table of EBIOS ports
  1665.     xor    bx,bx
  1666.     mov    ah,cmkey
  1667.     call    comnd
  1668.     jnc    comse1            ; nc = success
  1669.             ; failure is ok, fails for GETBAUD etc calling comstrt
  1670.     mov    bx,ebport        ; use current port
  1671.     inc    bx            ; here count from 1
  1672. comse1:    push    bx
  1673.     mov    ah,cmword        ; get a word (remote node name)
  1674.     mov    dx,offset decbuf    ; work buffer
  1675.     mov    word ptr decbuf,0    ; insert terminator
  1676.     mov    bx,offset ebhlp        ; help message
  1677.     call    comnd            ; get the name
  1678.     mov    ah,cmeol
  1679.     call    comnd            ; get a confirm
  1680.     pop    bx
  1681.     jnc    comse7
  1682.     ret                ; c = failure
  1683.  
  1684. comse7:    dec    bx            ; count from 0
  1685.     mov    ebport,bx        ; port number 0..3
  1686.     call    chkbios            ; EBIOS presence check
  1687.     jnc    comse7a            ; nc = success
  1688.     jmp    comsex            ; c = failure
  1689. comse7a:push    es
  1690.     mov    bx,ds
  1691.     mov    es,bx
  1692.     mov    bx,offset ebcoms    ; es:bx to ebcoms address
  1693.     mov    dx,ebport        ; port number
  1694.     mov    cx,51            ; number of bytes in ebcoms
  1695.     mov    ah,ebquery        ; get redirection table info
  1696.     int    rs232
  1697.     mov    ebcoms,0        ; query puts ebport in LANA, clear it
  1698.     cmp    decbuf,0        ; any new name given?
  1699.     je    comse4            ; e = no, presume name exists in EBIOS
  1700.     mov    si,offset decbuf    ; user input
  1701.     mov    di,offset ebcoms+2    ; where to store it
  1702.     mov    cx,16            ; 16 char NetBios name
  1703.     cld
  1704. comse2:    lodsb                ; get a new char
  1705.     or    al,al            ; null terminator?
  1706.     jne    comse3            ; ne = no, use it
  1707.     mov    al,' '            ; replace with space
  1708.     rep    stosb            ; do remaining spots
  1709.     jmp    short comse3b        ; carry on when done
  1710. comse3:    cmp    al,60h            ; lower case?
  1711.     jb    comse3a            ; b = no
  1712. ;;    and    al,not 20h        ; lower to upper case
  1713. comse3a:stosb                ; store it
  1714.     loop    comse2
  1715.  
  1716. comse3b:
  1717.     call    setnbname        ; setup local Netbios name
  1718.     jc    comse4
  1719.     mov    si,ds
  1720.     mov    es,si
  1721.     cld
  1722.     mov    ebcoms+2+16,0        ; no Listen required, just a Call
  1723.     mov    cx,8
  1724.     mov    si,offset deflname    ; our Netbios name
  1725.     mov    di,offset ebcoms+2+16+16
  1726.     rep    movsw
  1727.  
  1728.  
  1729. comse4:    mov    bx,offset ebcoms    ; es:bx to ebcoms structure
  1730.     mov    ebcoms+1,80h        ; force a network connection
  1731.     mov    ah,ebredir        ; do redirection
  1732.     xor    al,al
  1733.     mov    dx,ebport
  1734.     int    rs232
  1735.     or    ax,ax
  1736.     jz    comse5            ; ax = 0 is success
  1737.     push    ax
  1738.     mov    ah,prstr
  1739.     mov    dx,offset ebmsg3    ; cannot open network
  1740.     int    dos
  1741.     pop    ax
  1742.     xchg    ah,al
  1743.     xor    ah,ah
  1744.     call    decout
  1745.     pop    es
  1746.     stc
  1747.     ret
  1748. comse5:    pop    es
  1749.     cmp    ebcoms+2,' '        ; do we have a name?
  1750.     ja    comse6            ; a = yes
  1751.     mov    ah,prstr
  1752.     mov    dx,offset ebmsg2    ; say bad command
  1753.     int    dos
  1754.     stc                ; fail
  1755.     ret
  1756. comse6:    call    serrst            ; reset previous port
  1757.     mov    bx,offset portb1    ; use Bios data structure
  1758.     mov    ax,type prtinfo        ; portinfo item size
  1759.     mov    cx,ebport        ; actual port (0..3)
  1760.     mul    cx            ; times port
  1761.     add    bx,ax            ; new portb<n> offset
  1762.     mov    portval,bx
  1763.     mov    [bx].portrdy,1        ; say the comms port is ready
  1764.     or    nettype,ebios        ; indentify network type
  1765.     mov    flags.comflg,'E'    ; say EBIOS
  1766.     mov    portin,0        ; say port has been touched
  1767.     mov    pcnet,1
  1768.     clc                ; success
  1769.     ret
  1770. comsex:    mov    dx,offset nonetmsg    ; say network is not available
  1771.     mov    ah,prstr
  1772.     int    dos
  1773. comsex1:stc                ; failure
  1774.     ret
  1775.  
  1776. comstelapi:                ; Novell TELAPI
  1777.     mov    ah,cmword        ; get a word (remote node name)
  1778.     mov    dx,offset decbuf    ; work buffer
  1779.     mov    word ptr decbuf,0    ; insert terminator
  1780.     mov    bx,offset telhlp    ; help message
  1781.     call    comnd            ; get the name
  1782.     mov    ah,cmeol
  1783.     call    comnd            ; get a confirm
  1784.     jnc    comstel1        ; nc = ok so far
  1785.     ret                ; did not get a confirm
  1786. comstel1:cmp    decbuf,0        ; got new address?
  1787.     jne    comstel2        ; ne = yes
  1788.     cmp    word ptr internet,0    ; have we a previous address?
  1789.     jne    comstel6        ; ne = yes, use it instead
  1790.     jmp    short comstel5        ; no address, say illegal
  1791. comstel2:cmp    portin,0        ; inited port yet?
  1792.     jl    comstel8        ; l = no
  1793.     test    nettype,telapi        ; already doing TELAPI?
  1794.     jz    comstel7        ; z = no
  1795.     call    chknew            ; ask Resume or New
  1796.     jc    comstel6        ; c = Resume
  1797. comstel7:call    nethangup        ; hangup that connection
  1798. comstel8:xor    bx,bx            ; convert Internet address to binary
  1799.     xor    dx,dx            ; Internet field in dl, as a temp
  1800.     mov    word ptr internet,dx    ; clear Internet address
  1801.     mov    word ptr internet+2,dx
  1802.     mov    si,offset decbuf    ; fresh text
  1803.     cld
  1804. comstel3:lodsb                ; get ascii digit
  1805.     cmp    al,'.'            ; separator?
  1806.     jne    comstel4        ; ne = no
  1807.     inc    bx            ; next field
  1808.     cmp    bx,3            ; beyond last field
  1809.     ja    comstel5        ; a = yes, error
  1810.     jmp    short comstel3
  1811. comstel4:or    al,al            ; end of information?
  1812.     jz    comstel6        ; z = yes
  1813.     sub    al,'0'            ; strip ascii bias
  1814.     cmp    al,9            ; in digits?
  1815.     ja    comstel5        ; a = no
  1816.     mov    dl,internet[bx]        ; current field
  1817.     xor    dh,dh
  1818.     shl    dx,1            ; times two
  1819.     push    dx            ; save
  1820.     shl    dx,1            ; times four
  1821.     shl    dx,1            ; times eight
  1822.     pop    cx            ; recover times two
  1823.     add    dx,cx            ; plus two = times ten
  1824.     add    al,dl            ; plus current digit
  1825.     mov    internet[bx],al        ; save value
  1826.     jmp    short comstel3        ; next character
  1827.  
  1828. comstel5:mov    ah,prstr        ; say bad address construction
  1829.     mov    dx,offset telmsg1
  1830.     int    dos
  1831.     mov    dx,offset decbuf    ; show address
  1832.     call    prtasz
  1833.     stc
  1834.     ret
  1835. comstel6:call    serrst            ; end previous async session
  1836.     mov    portval,offset portn ; set Network port data structure address
  1837.     or    nettype,telapi        ; indentify network type
  1838.         mov     flags.comflg,'T'    ; set the comm port flag
  1839.     clc
  1840.     ret
  1841.  
  1842. comstes:mov    ah,cmword        ; TES get a word (remote node name)
  1843.     mov    dx,offset decbuf    ; work buffer
  1844.     mov    word ptr decbuf,0    ; insert terminator
  1845.     mov    comand.cmblen,49    ; length of buffer
  1846.     mov    bx,offset teshelp    ; help message
  1847.     call    comnd            ; get the name
  1848.     mov    temp,ax            ; save number of chars entered
  1849.     mov    ah,cmeol
  1850.     call    comnd
  1851.     mov    comand.cmblen,0        ; length of buffer back to normal
  1852.     jnc    comstes1
  1853.     ret
  1854. comstes1:mov    cx,0ffffh        ; TES presence check
  1855.     mov    ah,tesinstal        ; installation/status check
  1856.     call    tes_service
  1857.     jc    comstes2        ; c = error of some kind
  1858.     cmp    ax,'TE'            ; signature
  1859.     jne    comstes2        ; ne = not present
  1860.     cmp    cx,0ffffh        ; should change too
  1861.     jne    comstes3        ; ne = present
  1862. comstes2:mov    ah,prstr
  1863.     mov    dx,offset nonetmsg    ; say no network
  1864.     int    dos
  1865.     stc                ; say failure
  1866.     ret                ; end TES
  1867. comstes3:mov    tesport,dx        ; remember TES intercepted port
  1868.     call    serrst            ; close current port
  1869.     mov    portval,offset portn ; set Network port data structure address
  1870.     or    nettype,tes        ; indentify network type
  1871.         mov     flags.comflg,'I'    ; set the comm port flag
  1872.     cmp    decbuf,'*'        ; was show-all entered?
  1873.     jne    comstes4        ; ne = no
  1874.     jmp    teshosts        ; show known TES hosts
  1875. comstes4:mov    ax,temp            ; length of entered name
  1876.     or    al,tesname        ; plus preexisting name, if any
  1877.     or    ax,ax            ; anything present?
  1878.     jz    comstes9        ; z = no name, find existing session
  1879.     cmp    decbuf,0        ; anything to copy?
  1880.     je    comstes5        ; e = no, use existing name
  1881.     call    nethangup        ; hangup existing connection
  1882.     mov    si,offset decbuf
  1883.     mov    di,offset tesname
  1884.     call    strcpy            ; copy node name
  1885. comstes5:clc
  1886.     ret
  1887.  
  1888. comstes9:mov    tesses,1        ; search for an active/held session
  1889. comstes10:call    tesstate        ; get state of that session to AH
  1890.     test    ah,2            ; active?
  1891.     jnz    comstes12        ; nz = yes, use it
  1892.     inc    tesses            ; next session
  1893.     cmp    tesses,9        ; done all?
  1894.     jbe    comstes10        ; be = no
  1895.     mov    tesses,1        ; try for a held session
  1896. comstes11:call    tesstate        ; get state of that session to AH
  1897.     test    ah,1            ; on hold?
  1898.     jnz    comstes12        ; nz = yes, use it
  1899.     inc    tesses            ; next session
  1900.     cmp    tesses,9        ; done all?
  1901.     jbe    comstes11        ; be = no
  1902.     mov    tesses,0        ; say no session
  1903.     mov    ah,prstr
  1904.     mov    dx,offset tesnhost    ; give directions
  1905.     int    dos
  1906.     call    teshosts        ; show known hosts
  1907. comstes12:ret
  1908.  
  1909. comstn:    mov    ah,cmword        ; get a word (remote node name)
  1910.     mov    dx,offset decbuf    ; work buffer
  1911.     mov    word ptr decbuf,0    ; insert terminator
  1912.     mov    bx,offset tcphlp    ; help message
  1913.     call    comnd            ; get the name
  1914.     push    ax            ; save byte count
  1915.     mov    ah,cmeol
  1916.     call    comnd            ; get a confirm
  1917.     pop    ax
  1918.     jnc    comstn1            ; nc = ok so far
  1919.     ret                ; did not get a confirm
  1920.  
  1921. comstn1:mov    si,offset decbuf
  1922.     mov    di,offset tcphost
  1923.     or    ax,ax            ; anything new given?
  1924.     jnz    comstn2            ; nz = yes, copy it
  1925.     cmp    byte ptr [di],0        ; have a name already?
  1926.     jnz    comstn3            ; nz = yes
  1927.     stc                ; return failure (no host name)
  1928.     ret
  1929. comstn2:test    nettype,tcpnet        ; is there an active tcp session?
  1930.     jz    comstn2a        ; z = no
  1931.     call    chknew            ; ask about new/old connection
  1932.     jc    comstn3            ; c = resume old
  1933.     call    tcpclose        ; end old session
  1934. comstn2a:mov    byte ptr [di+32],0    ; force termination
  1935.     call    strcpy
  1936. comstn3:call    serrst            ; close current port
  1937.     mov    portval,offset portn ; set Network port data structure address
  1938.     mov    flags.comflg,'t'    ; what we want, may not have yet
  1939.         mov     nsbrk,1                 ; network BREAK supported
  1940.     mov    portin,0
  1941.     clc
  1942.     ret
  1943. COMS    ENDP
  1944.  
  1945. teshosts proc    near            ; TES, show list of hosts
  1946.     mov    ah,prstr
  1947.     mov    dx,offset tesnlist    ; show list of hosts
  1948.     int    dos
  1949.     push    es
  1950.     push    si
  1951.     mov    ah,tesgets        ; get TES known servers
  1952.     call    tes_service        ; cx gets qty
  1953.     mov    dx,offset decbuf    ; work buffer
  1954.     mov    word ptr decbuf,'  '    ; item spacing
  1955.     xor    di,di            ; line length counter
  1956.     or    cx,cx            ; any servers?
  1957.     jnz    teshost1        ; nz = some servers
  1958.     inc    cx            ; say one for loop
  1959.     push    cx
  1960.     mov    word ptr decbuf+2,'ON'    ; prefill with NONE
  1961.     mov    word ptr decbuf+4,'EN'
  1962.     mov    decbuf+6,0        ; asciiz
  1963.     mov    cx,6            ; length of "  NONE"
  1964.     jmp    short teshost3        ; show NONE
  1965. teshost1:push    cx            ; count of servers
  1966.     push    si            ; save master list pointer
  1967.     push    di
  1968.     mov    si,es:[si]        ; get offset of first name
  1969.     mov    di,dx            ; decbuf
  1970.     add    di,2            ; move into decbuf+2
  1971. teshost2:mov    al,es:[si]        ; get name char
  1972.     inc    si
  1973.     mov    [di],al            ; store name char
  1974.     inc    di
  1975.     or    al,al            ; at end?
  1976.     jnz    teshost2        ; nz = no
  1977.     pop    di
  1978.     pop    si            ; master list of offsets
  1979.     add    si,2            ; next item in list
  1980.     call    strlen            ; get length of name w/spaces
  1981.     add    di,cx            ; length of display line with name
  1982.     cmp    di,60            ; time to break line?
  1983.     jbe    teshost3        ; be = no
  1984.     push    dx
  1985.     mov    ah,prstr        ; break the screen line
  1986.     mov    dx,offset crlf
  1987.     int    dos
  1988.     pop    dx
  1989.     xor    di,di            ; say line is empty
  1990. teshost3:add    di,cx            ; current line length
  1991.     call    prtasz            ; show asciiz text at ds:dx
  1992.     pop    cx
  1993.     loop    teshost1        ; do all entries
  1994.     pop    si
  1995.     pop    es
  1996.     ret
  1997. teshosts endp
  1998.  
  1999. ; Perform TES function given in AH, but tell cmd interpreter to not prompt.
  2000. tes_service     proc    near
  2001.         push    ax
  2002.         push    si
  2003.         push    es
  2004.         mov     ax,ds
  2005.         mov     es,ax
  2006.     mov    si,offset tesquiet    ; cmd to say no prompting
  2007.     xor    al,al            ; no visible response please
  2008.     mov    ah,tesexec
  2009.         int     rs232
  2010.         pop     es
  2011.         pop     si
  2012.         pop     ax
  2013.         int     rs232            ; do the main request
  2014.         ret
  2015. tes_service     endp
  2016.  
  2017. ; TES - start or resume a TES connection
  2018. tesstrt    proc    near
  2019.     cmp    tesses,0        ; session yet?
  2020.     jne    tesstr2            ; ne = yes
  2021.     cmp    tesname,0        ; have a node name?
  2022.     jne    tesstr1            ; ne = yes
  2023.     jmp    tesstr4            ; find an existing connection, if any
  2024.  
  2025. tesstr1:push    si
  2026.     mov    si,offset tesname    ; node name
  2027.     mov    ah,tesnews        ; make a new session
  2028.     call    tes_service
  2029.     pop    si
  2030.      jmp    short tesstr4        ; double check on transistions
  2031.  
  2032.                     ; have a session, live or held
  2033. tesstr2:call    tesstate        ; get session status
  2034.     test    ah,2            ; active or being made so?
  2035.     jnz    tesstr3            ; nz = yes, connect to it
  2036.     test    ah,1            ; session on hold or being made so?
  2037.     jz    tesstr1            ; z = no, make a new one
  2038.     mov    ah,tesresume        ; resume a session
  2039.     mov    al,tesses        ; the session number
  2040.     call    tes_service
  2041.     shl    ah,1            ; get status into carry bit
  2042.     jc    tesstr4            ; c = problem, try to recover
  2043.  
  2044. tesstr3:cmp    tesname,0        ; have name yet?
  2045.     je    tesstr4            ; e = no, get it now
  2046.     mov    pcnet,2            ; have an active session
  2047.     mov    portn.portrdy,1        ; say port is ready
  2048.     clc
  2049.     ret
  2050.  
  2051. tesstr4:push    si            ; find an active session number
  2052.     push    es
  2053.     mov    temp,0            ; retry counter
  2054.     mov    tesses,1        ; session number
  2055. tesstr5:mov    ah,teslist        ; get TES session pointers
  2056.     call    tes_service        ; CX gets quantity of ACTIVE sessions
  2057. tesstr6:mov    al,es:[si]        ; get session status
  2058.     cmp    al,82h            ; making a session now?
  2059.     je    tesstr7            ; e = yes, good enough
  2060.     test    al,80h            ; in transitional status?
  2061.     jz    tesstr6b        ; z = no
  2062.     mov    ah,100
  2063.     call    pcwait            ; wait 100 ms
  2064.     inc    temp
  2065.     cmp    temp,10
  2066.     ja    tesstr6a        ; a = too many retries, quit
  2067.     jmp    short tesstr5        ; nz = yes, go around again
  2068. tesstr6b:mov    temp,0            ; clear retry counter
  2069.     test    al,2            ; 0=inactive, 1=on hold, 2=active?
  2070.     jnz    tesstr7            ; nz = active
  2071.     add    si,3            ; skip status byte, name offset
  2072.     inc    tesses            ; bump session number
  2073.     cmp    tesses,9        ; done all?
  2074.     jbe    tesstr6            ; be = no
  2075. tesstr6a:mov    tesses,0        ; no active session
  2076.     mov    portn.portrdy,0        ; say the comms port is not ready
  2077.     mov     pcnet,1            ; network is present and inactive
  2078.     stc                ; signal failure
  2079.     jmp    short tesstr8
  2080.                     ; set port ready, get host name
  2081. tesstr7:mov    portn.portrdy,1        ; say the comms port is ready
  2082.     mov     pcnet,2            ; network is present and active
  2083.     mov    di,offset tesname    ; readback asciiz name
  2084.     mov    byte ptr [di],0        ; clear the name field
  2085.     mov    si,es:[si+1]        ; get name ptr offset
  2086.     or    si,si            ; check for null pointer
  2087.     jz    tesstr6a        ; z = no name, dead session
  2088.     mov    cx,49            ; limit to 48 chars plus null
  2089. tesstr7a:mov    al,es:[si]        ; get a char
  2090.     inc    si
  2091.     mov    [di],al            ; store
  2092.     inc    di
  2093.     or    al,al            ; null?
  2094.     jz    tesstr7b        ; z = yes, stop here
  2095.     loop    tesstr7a        ; keep going
  2096. tesstr7b:clc                ; signal success
  2097. tesstr8:pop    es
  2098.     pop    si
  2099.     ret
  2100. tesstrt    endp
  2101.  
  2102. ; TES. Return session status in AH for session in tesses. Destroys AX
  2103. tesstate proc    near
  2104.     push    cx
  2105.     push    si
  2106.     push    es
  2107.     mov    ah,teslist        ; get session list
  2108.     call    tes_service
  2109.     mov    ah,0ffh            ; set up no session status
  2110.     mov    al,tesses        ; our session number, 1..9
  2111.     dec    al            ; base on zero here
  2112.     mov    ah,al
  2113.     shl    ah,1
  2114.     add    al,ah
  2115.     xor    ah,ah            ; times three
  2116.     add    si,ax            ; point to session structure es:[si]
  2117.     mov    ah,es:[si]        ; get session status byte
  2118. testat1:pop    es
  2119.     pop    si
  2120.     pop    cx
  2121.     ret
  2122. tesstate endp
  2123.  
  2124. ; Start Novell TELAPI session. Internet address is already binary
  2125. telstrt    proc    near
  2126.     mov    dx,word ptr internet    ; internet address, high part
  2127.     mov    cx,word ptr internet+2
  2128.     mov    bx,telport        ; Telnet port (23 decimal)
  2129.     push    es
  2130.     push    si
  2131.     xor    si,si            ; use TELAPI data structures, not ours
  2132.     mov    es,si            ; es:si = Telnet state record, theirs
  2133.     mov    di,offset telhostid    ; two byte host identifier in ds:di
  2134.     mov    ah,telopen        ; open the connection
  2135.     int    rs232
  2136.     mov    telses,ax        ; save TELAPI session number
  2137.     pop    si
  2138.     pop    es
  2139.     or    ax,ax            ; get status returned in AX
  2140.     jns    telstr1            ; ns = success
  2141.     cmp    ax,telinuse        ; socket is already connected? (-56)
  2142.      jne    telstr2            ; ne = no, else attach to it
  2143. telstr1:mov    portn.portrdy,1        ; say the comms port is ready
  2144.     mov     pcnet,2            ; network is present and active
  2145.     push    es
  2146.     mov    ax,ds
  2147.     mov    es,ax
  2148.     mov    si,offset teloption    ; es:si = Option data structure
  2149.     mov    word ptr [si],0        ; clear the numeric fields
  2150.     mov    word ptr [si+2],0
  2151.     mov    cx,2            ; set Binary Option, no data
  2152.     mov    bx,telses        ; session
  2153.     mov    ah,telioctl        ; ioctl to do it
  2154.     int    rs232
  2155.     mov    ax,100            ; wait 100 ms for options to settle
  2156.     call    pcwait
  2157.     mov    telstate,0        ; forget old char/line mode state
  2158.     pop    es
  2159.     clc                ; success
  2160.     ret
  2161.                     ; failure message display section
  2162. telstr2:mov    dx,offset telmsg51    ; network unreachable
  2163.     cmp    ax,telunreac        ; correct?
  2164.     je    telstr3            ; e = yes
  2165.     mov    dx,offset telmsg56    ; socket in use
  2166.     cmp    ax,telinuse
  2167.     je    telstr3
  2168.     mov    dx,offset telmsg60    ; timeout on connection attempt
  2169.     cmp    ax,teltmo
  2170.     je    telstr3
  2171.     mov    dx,offset telmsg61    ; connection refused
  2172.     cmp    ax,telrefuse
  2173.     je    telstr3
  2174.     mov    dx,offset telmsg64    ; host is down
  2175.     cmp    ax,teldwnhost
  2176.     je    telstr3
  2177.     mov    dx,offset telmsg67    ; unknown host
  2178.     cmp    ax,telunkhost
  2179.     je    telstr3
  2180.     mov    dx,offset telmsg301    ; no more space
  2181.     cmp    ax,telfull
  2182.     je    telstr3
  2183.     push    ax            ; unknown error, show error value
  2184.     mov    dx,offset telmsg2
  2185.     mov    ah,prstr
  2186.     int    dos
  2187.     pop    ax
  2188.     neg    ax            ; make positive number again
  2189.     call    decout            ; show error value, for now
  2190.     jmp    short telstr4
  2191. telstr3:mov    ah,prstr
  2192.     int    dos            ; show reason msg
  2193. telstr4:mov    ax,3000            ; show for three seconds
  2194.     call    pcwait
  2195.     mov    portn.portrdy,0        ; say port is not ready
  2196.     stc                ; fail
  2197.     ret
  2198. telstrt    endp
  2199.  
  2200. ; Check for presence of DECNET. Host name is in latservice.
  2201. ; Try LAT then try CTERM. Sets nettype for kind found.
  2202. ; Return carry clear if success, or carry set if failure.
  2203. chkdec    proc    near
  2204.     cmp    pcnet,2            ; net active now?
  2205.     jb    chkde2            ; b = no
  2206.     cmp    lathand,0        ; valid LAT handle?
  2207.     jne    chkde1            ; ne = yes
  2208.     cmp    decneth,0        ; valid LAT handle?
  2209.     je    chkde2            ; e = invalid handle
  2210. chkde1:    clc
  2211.     ret                ; return to active session
  2212.  
  2213. chkde2:    push    es
  2214.     and    nettype,not (declat+decnet) ; clear network type bits
  2215.     mov    al,latint        ; LAT interrupt 6Ah
  2216.     mov    ah,35h            ; get vector to es:bx
  2217.     int    dos
  2218.     mov    ax,es
  2219.     or    ax,ax            ; undefined interrupt?
  2220.     jz    chkde3            ; z = yes
  2221.     cmp    byte ptr es:[bx],0cfh    ; points at IRET?
  2222.     je    chkde3            ; e = yes, not installed
  2223.     cmp    word ptr es:[bx-3],'AL'    ; preceeding 3 bytes spell 'LAT'?
  2224.     jne    chkde3            ; ne = no, so no LAT, try CTERM
  2225.     cmp    byte ptr es:[bx-1],'T'
  2226.     jne    chkde3            ; ne = no, try CTERM
  2227.     or    nettype,declat        ; kind of network is LAT
  2228.     mov    latinems,0        ; assume LAT is not in EMS
  2229.     mov    latversion,2        ; say version 2
  2230.     cmp    byte ptr es:[bx-4],10    ; minor version number, reasonable?
  2231.     jae    chkde3            ; ae = no, say version 2
  2232.     mov    latversion,4        ; say version 4
  2233.     mov    ax,ds
  2234.     mov    es,ax
  2235.     mov    bx,offset rdbuf        ; temp work buffer
  2236.     mov    cx,20            ; say 20 bytes is plenty
  2237.     mov    dh,0ffh
  2238.     mov    ah,latinfo        ; get misc info
  2239.     xor    al,al            ; LAT bug remover
  2240.     int    latint
  2241.     test    ah,80h            ; failure?
  2242.     jnz    chkde3            ; e = yes
  2243.     cmp    rdbuf+2,1        ; is LAT in EMS?
  2244.     jne    chkde3            ; ne = no
  2245.     mov    latinems,1        ; say LAT is in EMS
  2246.                     ; now do CTERM too
  2247. chkde3:    mov    al,decint        ; CTERM interrupt 69h
  2248.     mov    ah,35h            ; get vector to es:bx
  2249.     int    dos
  2250.     mov    ax,es
  2251.     or    ax,ax            ; undefined interrupt?
  2252.     jz    chkde4            ; z = yes
  2253.     cmp    byte ptr es:[bx],0cfh    ; points at IRET?
  2254.     je    chkde4            ; e = yes
  2255.     mov    ax,dpresent        ; CTERM installation call
  2256.     int    decint
  2257.     cmp    al,0ffh            ; CTERM installed?
  2258.     jne    chkde4            ; ne = no
  2259.     or    nettype,decnet        ; kind of network is CTERM
  2260. chkde4:    pop    es
  2261.     test    nettype,declat+decnet    ; any DEC network found?
  2262.     jz    chkde5            ; z = no
  2263.     clc                ; clear means yes
  2264.     ret
  2265. chkde5:    stc                ; status is no net
  2266.     ret
  2267. chkdec    endp
  2268.  
  2269. ; Start DECNET link. Host name is in latservice, nettype has LAT or CTERM
  2270. ; kind bits. Return carry clear if success, or carry set if failure.
  2271. decstrt    proc    near
  2272.     cmp    pcnet,2            ; net active now?
  2273.     jb    decst2            ; b = no
  2274.     cmp    lathand,0        ; invalid LAT handle?
  2275.     jne    decst1            ; ne = no, have a connection
  2276.     cmp    decneth,0        ; invalid CTERM handle?
  2277.     je    decst2            ; e = yes, start the net
  2278. decst1:    mov     portval,offset portn ; set Network port data structure address
  2279.         mov     flags.comflg,'D'    ; set the comm port flag
  2280.     mov    portn.portrdy,1        ; say the comms port is ready
  2281.     clc
  2282.     ret                ; return to active session
  2283.  
  2284. decst2:    push    es            ; used a lot here
  2285.     call    chkdec            ; get net type
  2286.     jnc    decst3            ; nc = have a CTERM or LAT kind
  2287.     jmp    decst16            ; c = net not found
  2288.  
  2289. decst3:    cmp    latservice,0        ; node name present?
  2290.     jne    decst4            ; ne = yes
  2291.     mov    ah,prstr
  2292.     mov    dx,offset noname    ; say host name is required
  2293.     int    dos
  2294.     pop    es
  2295.     stc                ; fail
  2296.     ret
  2297.  
  2298. decst4:    test    nettype,declat        ; LAT is available?
  2299.     jnz    decst5            ; nz = yes
  2300.     jmp    decst13            ; z = no, try CTERM
  2301.  
  2302. decst5:    and    nettype,not declat    ; presume failure
  2303.     cmp    latversion,4        ; version 4?
  2304.     jb    decst6            ; b = no, earlier, do our own SCB
  2305.     mov    ax,latscbget        ; get LAT interior SCB addr to es:bx
  2306.     mov    dh,0ffh
  2307.     int    latint
  2308.     or    ah,ah            ; success?
  2309.     jnz    decst6            ; nz = no
  2310.     mov    ax,es
  2311.     mov    word ptr latscbptr+2,ax    ; address of SCB within LAT
  2312.     mov    word ptr latscbptr,bx
  2313.     jmp    short decst8        ; go setup structure with ax:bx
  2314.  
  2315. decst6:    cmp    word ptr latscbptr+2,0    ; any segment allocated now?
  2316.     jne    decst8            ; ne = yes, do not malloc one here
  2317.     cmp    tv_mode,0        ; running under Windows or DV?
  2318.     je    decst6a            ; e = no, ok to try local SCB
  2319.     jmp    decst12b        ; can't use local so no LAT today
  2320. decst6a:mov    bx,870+15        ; size of LAT SCB, bytes, rounded up
  2321.     mov    cl,4
  2322.     shr    bx,cl            ; bytes to paragraphs
  2323.     mov    temp,bx            ; save requested paragraphs
  2324.     mov    ah,alloc        ; allocate memory, ax gets segment
  2325.     int    dos            ; bx gets # paragraphs allocated
  2326.     jnc    decst7            ; nc = success
  2327.     jmp    decst13            ; fail, go try CTERM
  2328. decst7:    mov    latseg,ax
  2329.     mov    word ptr latscbptr+2,ax    ; remember seg of SCB
  2330.     mov    es,ax
  2331.     xor    di,di            ; es:di is destination
  2332.     xor    ax,ax            ; get word of zeros
  2333.     mov    word ptr latscbptr+0,ax    ; remember offset (0) of SCB
  2334.     mov    cx,bx            ; paragraphs obtained
  2335.     shl    cx,1
  2336.     shl    cx,1
  2337.     shl    cx,1            ; words
  2338.     cld
  2339.     rep    stosw            ; clear the SCB
  2340.     cmp    temp,bx            ; wanted vs allocated (bx) paragraphs
  2341.     jbe    decst8            ; be = enough, setup structure
  2342.     jmp    decst12            ; deallocate memory and try CTERM
  2343.  
  2344. decst8:    les    bx,latscbptr
  2345.     mov    es:[bx].slottbl,slotbf1    ; offset of first buffer
  2346.     mov    es:[bx].slottbl+2,slotbf2 ; offset of second buffer
  2347.     mov    es:[bx].slotqty,2    ; say two buffers
  2348.  
  2349. decst9:    les    di,latscbptr        ; set es:di to SCB
  2350.     mov    si,offset latservice    ; get host name
  2351.     mov    cx,17            ; 17 bytes
  2352.     cld
  2353.     rep    movsb            ; insert host name
  2354.     mov    ax,latopen        ; open a LAT session
  2355.     mov    di,offset latpwd    ; es:di optional asciiz LAT password
  2356.     cmp    byte ptr [di],0        ; any name entered?
  2357.     je    decst10            ; e = no
  2358.     and    al,0fh            ; open as AX = 0d0fh if with password
  2359. decst10:cmp    latversion,4        ; LAT version 4?
  2360.     jb    decst11            ; b = no, use version 2
  2361.     mov    al,1            ; v4 form
  2362.     mov    bx,word ptr latscbptr    ; SCB
  2363.     mov    cx,ds
  2364.     mov    word ptr es:[bx].lat_pwd+2,cx ; set the pointer segment
  2365.     mov    word ptr es:[bx].lat_pwd,di  ; address of the password buffer
  2366.     mov    dx,di
  2367.     call    strlen            ; password string length to cx
  2368.     mov    es:[bx].pwd_len,cl    ; length of the password
  2369.     or    cx,cx            ; is there a password?
  2370.     jnz    decst11            ; nz = yes
  2371.     mov    word ptr es:[bx].lat_pwd,cx ; no, clear fields
  2372.     mov    word ptr es:[bx].lat_pwd+2,cx
  2373.     mov    byte ptr es:[bx].pwd_len,cl
  2374. decst11:mov    bx,word ptr latscbptr    ; open needs es:bx == SCB
  2375.     mov    dh,0ffh
  2376.     int    latint
  2377.     or    ah,ah            ; status byte
  2378.     jnz    decst12            ; nz = failure, clean up, try CTERM
  2379.     mov    dh,0ffh
  2380.     mov    lathand,dx        ; handle returned in dl, 0ffh in dh
  2381.     or    nettype,declat        ; say LAT session is active
  2382.     jmp    decst17            ; finish startup info
  2383.                     ; LAT startup failure
  2384. decst12:mov    ax,latseg        ; stored segment of memory block
  2385.     or    ax,ax            ; did we use it?
  2386.     jz    decst12a        ; z = no
  2387.     mov    es,ax            ; allocated segment, unneed now
  2388.     mov    ah,freemem        ; free it again
  2389.     int    dos
  2390.     mov    word ptr latscbptr+2,0    ; clear pointer for test below
  2391. decst12a:cmp    word ptr latscbptr+2,0    ; in use as LAT internal perhaps?
  2392.     je    decst12b        ; e = no
  2393.     les    bx,latscbptr
  2394.     mov    ax,latscbfree        ; free internal LAT SCB
  2395.     int    latint
  2396. decst12b:xor    ax,ax
  2397.     mov    latseg,ax        ; say not used
  2398.     mov    lathand,ax        ; invalidate the handle
  2399.     mov    word ptr latscbptr+0,ax    ; clear SCB pointer
  2400.     mov    word ptr latscbptr+2,ax
  2401.     and    nettype,not declat    ; fall through to try CTERM
  2402.  
  2403. decst13:test    nettype,decnet        ; is CTERM available?
  2404.     jz    decst16            ; z = no
  2405.     and    nettype,not decnet    ; presume failure
  2406.     mov    ax,decseg        ; scb memory segment, if non-zero
  2407.     or    ax,ax            ; allocated already?
  2408.     jnz    decst14            ; nz = yes, segment is in ax
  2409.     mov    ax,dgetscb        ; get CTERM SCB size
  2410.     int    decint
  2411.     add    ax,15            ; round up byte count
  2412.     mov    cl,4
  2413.     shr    ax,cl            ; bytes to paragraphs
  2414.     mov    bx,ax
  2415.     mov    temp,ax            ; save requested paragraphs
  2416.     mov    ah,alloc        ; allocate memory
  2417.     int    dos            ; bx gets # paragraphs allocated
  2418.     jc    decst16            ; c = failure
  2419.     mov    decseg,ax        ; store address of memory block
  2420.     cmp    temp,bx            ; wanted vs allocated paragraphs
  2421.     jb    decst15            ; b = not enough, fail
  2422.  
  2423. decst14:mov    bx,offset latservice    ; ds:bx = node name
  2424.     mov    es,ax            ; ax holds scb segment
  2425.     xor    dx,dx            ; es:dx = SCB address
  2426.     mov    ax,dopen        ; open session
  2427.     int    decint
  2428.     or    ax,ax            ; > 0 means session handle, else error
  2429.     jle    decst15            ; le = error
  2430.     mov    decneth,ax        ; store handle
  2431.     or    nettype,decnet        ; network type is DECnet
  2432.     jmp    short decst17        ; success
  2433.                     ; CTERM startup failure
  2434. decst15:push    ax            ; save error number in ax
  2435.     mov    ax,decseg        ; allocated memory segment
  2436.     mov    es,ax
  2437.     mov    ah,freemem        ; free allocated memory segment @ES
  2438.     int    dos            ; free the block
  2439.     mov    decseg,0        ; clear remembered segment address
  2440.     mov    ah,prstr
  2441.     mov    dx,offset decmsg1    ; cannot create session
  2442.     int    dos
  2443.     mov    dx,offset decmsg3    ; DEC Error #
  2444.     int    dos
  2445.     pop    ax            ; recover error number (negative)
  2446.     neg    ax
  2447.     call    decout            ; error number
  2448.     mov    decneth,0        ; invalidate the handle
  2449.     and    nettype,not decnet
  2450.  
  2451. decst16:mov    pcnet,0            ; no net
  2452.     mov    portn.portrdy,0        ; port is not ready
  2453.     pop    es
  2454.     stc                ; status is error
  2455.     ret
  2456.                     ; LAT or CTERM success
  2457. decst17:mov    pcnet,2            ; say net is present and active
  2458.     mov     portval,offset portn    ; set Network port structure address
  2459.         mov     flags.comflg,'D'    ; set the comm port flag
  2460.     mov    portn.portrdy,1        ; say the comms port is ready
  2461.     mov    ax,100            ; wait 100 ms for DECnet to get ready
  2462.     call    pcwait
  2463.     pop    es
  2464.     clc
  2465.     ret
  2466. decstrt    endp
  2467.  
  2468. ; Display list of LAT service names. Presumes LAT presence checks have passed
  2469. latlst    proc    near
  2470.     push    es
  2471.     push    bx
  2472.     mov    ah,prstr
  2473.     mov    dx,offset dnetsrv    ; header
  2474.     int    dos
  2475.     push    ds
  2476.     pop    es
  2477.     mov    si,2            ; chars in line counter
  2478. latlst1:mov    bx,offset decbuf+2     ; es:bx = temp buffer for a name
  2479.     mov    word ptr [bx-2],'  '    ; indent
  2480.     mov    byte ptr [bx],0        ; and a null terminator
  2481.     mov    ax,latsrv        ; get next LAT service name
  2482.     mov    dh,0ffh
  2483.     int    latint
  2484.     or    ah,ah            ; check status
  2485.     jnz    latlst2            ; nz = done (no more names)
  2486.     mov    dx,offset decbuf    ; name ptr is in es:bx (our buffer)
  2487.     call    prtasz            ; show asciiz name
  2488.     call    strlen            ; get current length
  2489.     add    si,cx            ; count chars on this line
  2490.     cmp    si,60            ; enough on line already?
  2491.     jbe    latlst1            ; be = no
  2492.     mov    ah,prstr        ; break the screen line
  2493.     mov    dx,offset crlf
  2494.     int    dos
  2495.     mov    si,2            ; reset line count
  2496.     jmp    short latlst1        ; do it again
  2497. latlst2:pop    bx
  2498.     pop    es
  2499.     ret
  2500. latlst    endp
  2501.  
  2502. ; Check which Interrupt ReQuest line the port uses. Technique: allow interrupt
  2503. ; on transmitter holding register empty, test for that condition first with
  2504. ; IRQ 4 and then IRQ 3. Returns with IRQ values set and carry clear if success
  2505. ; or carry set if failure. [jrd]
  2506. chkint    proc    near
  2507.     mov    bl,flags.comflg        ; port 1..4
  2508.     dec    bl
  2509.     xor    bh,bh
  2510.     mov    al,portirq[bx]        ; pre-specified IRQ, if any
  2511.     or    al,al            ; IRQ specified already?
  2512.     jz    chkint5            ; z = no, find IRQ 4 or 3
  2513.                     ; IRQ specified, in AL
  2514.     mov    di,sp            ; do push sp test for XT vs 286 class
  2515.     push    sp            ; XT pushes sp-2, 286's push old sp
  2516.     pop    cx            ; recover pushed value, clean stack
  2517.     sub    di,cx            ; non-zero if < 80286, no slave 8259
  2518.     cmp    al,2            ; using IRQ 2?
  2519.     jne    chkint1            ; ne = no
  2520.     or    di,di            ; cascaded 8259?
  2521.     jnz    chkint1            ; nz = no
  2522.     add    al,7            ; map IRQ 2 to IRQ 9
  2523. chkint1:cmp    al,15            ; larger than legal IRQ?
  2524.     ja    chkint3            ; a = yes, fail
  2525.     or    di,di            ; 286 or above (cascaded 8259)?
  2526.     jz    chkint3            ; z = yes
  2527.     cmp    al,7            ; larger than legal for single 8259?
  2528.     jbe    chkint3            ; be = no
  2529. chkint2:stc                ; fail
  2530.     ret
  2531. chkint3:mov    cl,al            ; IRQ 0..15
  2532.     mov    bx,1
  2533.     shl    bx,cl            ; bit position of IRQ 0..15
  2534.     or    bl,bh            ; copy bit to bl
  2535.     mov    modem.mddis,bl        ; mask to disable IRQ
  2536.     not    bl            ; 0 means enable
  2537.     mov    modem.mden,bl        ; mask to enable IRQ
  2538.     and    al,7            ; IRQ, lower three bits
  2539.     mov    ah,al            ; make a copy
  2540.     add    ah,60h            ; specific EOI control code
  2541.     mov    modem.mdmeoi,ah        ; specific EOI control command
  2542.     add    al,8            ; IRQ 0 starts at Int 8
  2543.     xor    ah,ah
  2544.     mov    modem.mdintv,ax        ; Interrupt number
  2545.     mov    modem.mdmintc,20h    ; master 8259 control address
  2546.     or    bh,bh            ; on cascaded 8259?
  2547.     jz    chkint4            ; z = no
  2548.     or    modem.mdmintc,80h    ; slave 8259 control address (0a0h)
  2549.     add    modem.mdintv,70h-8    ; Interrupt number for IRQ 8..15
  2550. chkint4:call    serrst            ; run usage test, to be sure
  2551.     mov    portin,0
  2552.     mov    intkind,0        ; clear interrupt cause
  2553.     call    inttest            ; run test
  2554.     jc    chkint5            ; c = failed, try regular IRQs
  2555.     ret
  2556.  
  2557. chkint5:call    serrst            ; find IRQ 4 or 3 by usage tests
  2558.     mov    portin,0
  2559.     mov    modem.mddis,(1 shl 4)    ; IRQ 4 test. mask to disable IRQ 4
  2560.     mov    modem.mden,not (1 shl 4); mask to enable IRQ 4
  2561.     mov    modem.mdmeoi,20h    ; use general in case we guess wrong
  2562.     mov    modem.mdintv,8+4    ; IRQ 4 interrupt vector (0ch)
  2563.     mov    modem.mdmintc,20h    ; use master 8259 here
  2564.     mov    intkind,0        ; clear interrupt cause
  2565.     call    inttest
  2566.     jc    chkint6            ; c = failed
  2567.     mov    modem.mdmeoi,60h+4    ; use specific EOI for IRQ4 level
  2568.     clc                ; this setup worked
  2569.     ret
  2570.                     ; IRQ 3 test
  2571. chkint6:mov    modem.mddis,(1 shl 3)    ; mask to disable IRQ 3
  2572.     mov    modem.mden,not (1 shl 3); mask to enable IRQ 3
  2573.     mov    modem.mdmeoi,20h    ; use general in case we guess wrong
  2574.     mov    modem.mdintv,8+3    ; IRQ 3 interrupt vector
  2575.     mov    intkind,0        ; clear interrupt cause
  2576.     call    inttest
  2577.     jc    chkint7            ; c = failed
  2578.     mov    modem.mdmeoi,60h+3    ; use specific EOI for IRQ3 level
  2579.     clc                ; this setup worked
  2580.     ret
  2581.  
  2582. chkint7:call    serrst            ; reset port, auto test did not work
  2583.     mov    modem.mdmintc,20h    ; use master 8259 Int controller
  2584.     cmp    flags.comflg,1        ; COM1?
  2585.     je    chkint8            ; e = yes, use IRQ 4
  2586.     cmp    isps2,0            ; IBM PS/2 Model 50 or above?
  2587.     jne    chkint9            ; ne = yes, other COMs use IRQ 3
  2588.     cmp    flags.comflg,3        ; COM2, COM3, or COM4?
  2589.     jne    short chkint9        ; ne = COM2 or COM4, use IRQ 3
  2590. chkint8:cmp    modem.mddat,02f8h    ; really COM2 material for PCjr?
  2591.     je    chkint9            ; e = yes, use COM2 addresses
  2592.     mov    modem.mdmeoi,60h+4    ; use specific EOI for IRQ4 level
  2593.     mov    modem.mddis,(1 shl 4)    ; IRQ 4 test. mask to disable IRQ 4
  2594.     mov    modem.mden,not (1 shl 4); mask to enable IRQ 4
  2595.     mov    modem.mdintv,8+4    ; IRQ 4 interrupt vector (0ch)
  2596.     clc
  2597.     ret
  2598. chkint9:mov    modem.mdmeoi,60h+3    ; use specific EOI for IRQ 3 level
  2599.     mov    modem.mddis,(1 shl 3)    ; mask to disable IRQ 3
  2600.     mov    modem.mden,not (1 shl 3); mask to enable IRQ 3
  2601.     mov    modem.mdintv,8+3    ; IRQ 3 interrupt vector
  2602.     clc
  2603.     ret
  2604.  
  2605. inttest:call    serini            ; setup port for given IRQ
  2606.     jc    inttes2            ; c = failure
  2607.     mov    dx,modem.mddat
  2608.     inc    dx            ; interrupt enable reg (3f9h)
  2609.     cli
  2610.     mov    al,2            ; set xmtr holding reg empty interrupt
  2611.     out    dx,al
  2612.     jmp    $+2
  2613.     out    dx,al            ; again, because first may be missed
  2614.     sti
  2615.     mov    ax,1            ; wait one millisec for interrupt
  2616.     call    pcwait            ;  to occur
  2617.     test    intkind,2        ; check cause of interrupt, ours?
  2618.     jz    inttes2            ; z = no, test failed
  2619.     call    serrst            ; reset port
  2620.     clc                ; this setup worked
  2621.     ret
  2622. inttes2:call    serrst            ; reset port
  2623.     stc                ; failure
  2624.     ret
  2625. chkint    endp
  2626.  
  2627. ; Test presently selected serial port for having a real 8250 UART.
  2628. ; Return carry clear if 8250 present,
  2629. ;  else carry set and flags.comflg in ascii digits for system Bios or
  2630. ;  carry set for network.
  2631. ; Method is to check UART's Interrupt Identification Register for high
  2632. ; five bits being zero; IBM does it this way. Assumes port structure
  2633. ; has been initialized with addresses of UART.    21 Feb 1987 [jrd]
  2634. ; 29 May 1987 Add double check by reading Line Status Register. [jrd]
  2635.  
  2636. chkport    proc    near
  2637.     cmp    flags.comflg,4        ; non-UART port?
  2638.     ja    chkporx            ; a = yes
  2639.     cmp    flags.comflg,0        ; undefined port?
  2640.     je    chkporx            ; e = yes
  2641.     push    ax
  2642.     push    dx
  2643.     mov    dx,modem.mdiir        ; UART Interrupt Ident reg (3FAh/2FAh)
  2644.     in    al,dx            ; read UART's IIR
  2645.     test    al,30h            ; are these bits set?
  2646.     jnz    chkpor1            ; nz = yes, not an 8250/16450/16550A
  2647.     mov    dx,modem.mdstat        ; line status register
  2648.     in    al,dx             ; read to clear UART BI, FE, PE, OE bits
  2649.     jmp    $+2            ; pause, for chip access timing
  2650.     in    al,dx            ; these bits should be cleared
  2651.     test    al,8eh            ; are they cleared?
  2652.     jnz    chkpor1            ; nz = no, not an 8250/16450/16550A
  2653.     pop    dx
  2654.     pop    ax
  2655.     clc                ; clear carry (say 8250/etc)
  2656.     ret
  2657. chkpor1:pop    dx
  2658.     pop    ax
  2659.     add    flags.comflg,'0'    ; set Bios usage flag (ascii digit)
  2660. chkporx:stc                ; set carry (say no 8250/etc)
  2661.     ret
  2662. chkport    endp
  2663.  
  2664. ; Check for presence of IBM EBIOS
  2665. ; Returns carry clear if EBIOS present, else carry set
  2666. chkbios    proc    near
  2667.     mov    dx,ebport        ; port 0..3
  2668.     mov    ax,ebpresent*256+0ffh    ; IBM EBIOS presence check
  2669.     int    rs232
  2670.     jc    chkbios1        ; c = failure
  2671.     or    ax,ax            ; returns ax = 0 if present
  2672.     jnz    chkbios1        ; nz = not present
  2673.     clc
  2674.     ret
  2675. chkbios1:stc                ; IBM EBIOS not present
  2676.     ret
  2677. chkbios    endp
  2678.  
  2679. ; Set the baud rate for the current port, based on the value
  2680. ; in the portinfo structure.  Returns carry clear.
  2681.  
  2682. BAUDST    PROC    NEAR
  2683.     mov    dx,offset bdtab        ; baud rate table, ascii
  2684.     xor    bx,bx            ; help is the table itself
  2685.     mov    ah,cmkey        ; get keyword
  2686.     call    comnd
  2687.     jc    baudst1            ; c = failure
  2688.     push    bx            ; save result
  2689.     mov    ah,cmeol        ; get confirmation
  2690.     call    comnd
  2691.     pop    bx
  2692.     jc    baudst1            ; c = failure
  2693.     mov    si,portval
  2694.     mov    ax,[si].baud        ; remember original value
  2695.     mov    [si].baud,bx        ; set the baud rate
  2696.     call    dobaud            ; use common code
  2697.     clc
  2698. baudst1:ret
  2699. BAUDST    ENDP
  2700.  
  2701. DOBAUD    PROC    NEAR
  2702.     cmp    portin,-1        ; port used yet?
  2703.     jne    dobd3            ; ne = yes, go get rate
  2704.     mov    bl,flags.comflg        ; pass current port ident
  2705.     call    comstrt            ; do SET PORT command now
  2706.     jnc    dobd3            ; nc = success
  2707. dobd4:    stc
  2708.     ret                ; failure
  2709. dobd3:    push    ax            ; save some regs
  2710.     mov    al,flags.comflg        ; comms port
  2711.     cmp    al,'E'            ; EBIOS?
  2712.     je    dobd5            ; e = yes
  2713.     cmp    al,'4'            ; UART or Bios?
  2714.     ja    dobd1            ; a = no, networks
  2715.     call    chkport            ; check port for real 8250 UART
  2716. dobd5:    mov    bx,portval        ; pointer to port data structure
  2717.     mov    ax,[bx].baud        ; check if new rate is valid
  2718.     shl    ax,1            ; make a word index
  2719.     mov    bx,offset bddat        ; start of table
  2720.     cmp    flags.comflg,'0'    ; Bios?
  2721.     jb    dobd0a            ; b = no, UART
  2722.     mov    bx,offset clbddat    ; use Bios speed parameters
  2723. dobd0a:    add    bx,ax
  2724.     mov    ax,[bx]            ; data to output to port
  2725.     cmp    ax,0FFh            ; unimplemented baud rate?
  2726.     jne    dobd0            ; ne = no
  2727.     mov    ah,prstr
  2728.     mov    dx,offset badbd        ; give an error message
  2729.     int    dos
  2730.     jmp    dobd1
  2731.  
  2732. dobd0:    mov    dl,flags.comflg        ; get coms port (1..4, letters)
  2733.     cmp    dl,4            ; running on a real uart?
  2734.     jbe    dobd2            ; be = yes, the real thing
  2735.     cmp    dl,'E'            ; EBIOS?
  2736.     je    dobd6            ; e = yes
  2737.     cmp    dl,'4'            ; Bios?
  2738.     ja    dobd1            ; a = no, network
  2739.     or    dl,dl            ; zero (undefined port)?
  2740.     jz    dobd1            ; z = yes, just exit
  2741.     and    dl,7            ; use lower three bits
  2742.     dec    dl            ; count ports as 0..3 for Bios
  2743.     jmp    short dobd7
  2744. dobd6:    mov    dx,ebport        ; get EBIOS port (0..3)
  2745. dobd7:    xor    dh,dh
  2746.     xor    ah,ah            ; set serial port
  2747.     int    rs232            ; Bios: set the parameters
  2748.          jmp    short dobd1        ; and exit
  2749.  
  2750. dobd2:    push    ax            ; UART, remember value to output
  2751.     mov    dx,modem.mdcom        ; LCR -- Initialize baud rate
  2752.     in    al,dx            ; get it
  2753.     mov    bl,al            ; make a copy
  2754.     or    ax,80H        ; turn on DLAB bit to access divisor part
  2755.     out    dx,al
  2756.     mov    dx,modem.mddat
  2757.     pop    ax            ; set the baud rate divisor
  2758.     out    dx,al
  2759.     inc    dx            ; next address for high part
  2760.     mov    al,ah            ; set high part of divisor
  2761.     out    dx,al
  2762.     mov    dx,modem.mdcom        ; LCR again
  2763.     mov    al,bl            ; get original setting from bl
  2764.     out    dx,al            ; restore it
  2765. dobd1:    pop    ax            ; restore regs
  2766.     clc
  2767.     ret
  2768. DOBAUD    ENDP
  2769.  
  2770. ; Get the current baud rate from the serial card and set it
  2771. ; in the portinfo structure for the current port.  Returns normally.
  2772. ; This is used during initialization.
  2773.  
  2774. GETBAUD    PROC    NEAR
  2775.     push    ax
  2776.     push    bx
  2777.     mov    bx,portval
  2778.     mov    al,flags.comflg
  2779.     cmp    al,4            ; UART?
  2780.     ja    getb3            ; a = no, Bios or Networks
  2781.     cmp    portin,-1        ; port unused?
  2782.     jne    getbud            ; ne = no, used, go get rate
  2783.     mov    bl,al            ; pass current port ident
  2784.     call    comstrt            ; do SET PORT command now
  2785.     jnc    getbud            ; nc = success
  2786. getb3:    pop    bx
  2787.     pop    ax
  2788.     ret                ; failure
  2789. getbud:    push    cx            ; save some regs
  2790.     push    dx
  2791.     mov    dx,modem.mdcom         ; get current Line Control Register value
  2792.     in    al,dx
  2793.     mov    bl,al            ; save it
  2794.     or    ax,80H              ; turn on to access baud rate generator
  2795.     out    dx,al
  2796.     mov    dx,modem.mddat        ; Divisor latch
  2797.     inc    dx
  2798.     in    al,dx            ; get high order byte
  2799.     mov    ah,al            ; save here
  2800.     dec    dx
  2801.     in    al,dx            ; get low order byte
  2802.     push    ax    
  2803.     mov    dx,modem.mdcom        ; Line Control Register
  2804.     mov    al,bl            ; restore old value
  2805.     out    dx,al
  2806.     pop    ax
  2807.     cmp    ax,0FFFFH        ; who knows what this is
  2808.     je    getb2
  2809.     mov    bx,offset bddat        ; find rate's offset into table
  2810.     xor    cl,cl            ; keep track of index
  2811. getb0:    cmp    ax,[bx]            ; observed vs table divisor
  2812.     je    getb1            ; e = found a match
  2813.     inc    cl            ; next table index
  2814.     cmp    cl,baudlen        ; at the end of the list?
  2815.     jge    getb2            ; ge = yes, quit
  2816.     add    bx,2            ; next table entry
  2817.     jmp    short getb0
  2818. getb1:    xor    ch,ch
  2819.     mov    bx,portval
  2820.     mov    [bx].baud,cx        ; set baud rate
  2821. getb2:    pop    dx            ; restore regs
  2822.     pop    cx
  2823.     pop    bx
  2824.     pop    ax
  2825.     clc
  2826.     ret
  2827. GETBAUD    ENDP
  2828.  
  2829. ; Get Char from    serial port buffer.
  2830. ; returns carry set if no character available at port, otherwise
  2831. ; returns carry clear with char in al, # of chars in buffer in dx.
  2832. PRTCHR  PROC    NEAR
  2833.     cmp    holdscr,0        ; Holdscreen in effect?
  2834.     jne    prtch0a            ; ne = yes, do not read
  2835.     call    chkxon            ; see if we need to xon
  2836.     cmp    repflg,0        ; REPLAY?
  2837.     je    prtchn1            ; e = no
  2838.     jmp    prtch30            ; yes, do replay file reading
  2839. prtchn1:mov    al,flags.comflg        ; get kind of port
  2840.     cmp    al,'0'            ; Bios or network?
  2841.     jb    prtch0            ; b = no, UART
  2842.     cmp    al,'4'            ; Bios?
  2843.     ja    prtchn            ; a = no
  2844.     jmp    prtch7            ; be = yes, else networks
  2845. prtchn:    cmp    al,'E'            ; EBIOS?
  2846.     je    prtch6            ; e = yes
  2847.     mov    dx,count        ; chars in buffer now
  2848.     cmp    dx,bufsiz-nbuflen    ; room left for more network data?
  2849.     ja    prtch1            ; a = no, read current buffer
  2850.     cmp    al,'U'            ; UB network?
  2851.     je    prtchn2
  2852.     cmp    al,'C'            ; 3Com BAPI interface?
  2853.     je    prtchn2            ; e = yes
  2854.     cmp    al,'I'            ; TES?
  2855.     jne    prtchn5            ; ne = no
  2856.     or    dx,dx            ; anything left in our buffer?
  2857.     jnz    prtch1            ; nz = yes, use it first
  2858.     call    tesrcv            ; do TES block receive
  2859.     jmp    short prtch0
  2860. prtchn5:cmp    al,'T'            ; Novell TELAPI?
  2861.     je    prtchn2            ; e = yes
  2862.     cmp    al,'W'            ; Novell network?
  2863.     je    prtchn2            ; e = yes
  2864. prtchn6:cmp    al,'t'            ; TCP Telnet?
  2865.     jne    prtchn3            ; ne = no
  2866. prtchn2:or    dx,dx            ; anything left in our buffer?
  2867.     jnz    prtch1            ; nz = yes, use it first
  2868.     call    ubrecv                  ; do a UB receive
  2869.     jmp    short prtch0
  2870. prtchn3:cmp    al,'D'            ; DECnet?
  2871.     jne    prtchn4            ; ne = no
  2872.     jmp    decrcv            ; DECnet receive char
  2873. prtchn4:call    receive                 ; start next NetBios receive (async)
  2874. prtch0:    cmp    count,0            ; any characters available?
  2875.     jnz    prtch1            ; nz = yes, get one
  2876. prtch0a:xor    dx,dx            ; return count of zero
  2877.     stc                ; say no data
  2878.     ret
  2879. prtch1:    push    si            ; save si
  2880.     cli        ; interrupts off, to keep srcpnt & count consistent
  2881.     mov    si,srcpnt        ; address of next available slot in buffer
  2882.     sub    si,count        ; minus number of unread chars in buffer
  2883.     cmp    si,offset source    ; located before start of buf?
  2884.     jae    prtch2            ; ae = no
  2885.     add    si,bufsiz        ; else do arithmetic modulo bufsiz
  2886. prtch2:    mov    al,byte ptr [si]    ; get a character into al
  2887.     dec    count            ; one less unread char now
  2888.     sti                ; interrupts back on now
  2889.     pop    si
  2890.     mov    dx,count        ; return # of chars in buffer
  2891.     clc
  2892.     ret
  2893.                     ; EBIOS calls
  2894. prtch6:    mov    dx,ebport        ; port 0..3
  2895.     mov    ah,ebrcv        ; IBM EBIOS receive /no wait
  2896.     int    rs232            ; does line check then char ready chk
  2897.     test    ah,8ch            ; timeout, framing error, parity error?
  2898.     jnz    prtch8            ; nz = error, no char
  2899.     jz    prtch10            ; z = success, process char in AL
  2900.                     ; Bios calls
  2901. prtch7:    xor    dh,dh            ; assume port 1, find current port
  2902.     mov    dl,flags.comflg        ; get port number (1..4)
  2903. prtch7a:or    dl,dl            ; zero (no such port)?
  2904.     jz    prtch8            ; z = yes, don't access it
  2905.     and    dl,7            ; use low three bits
  2906.     dec    dl            ; address ports as 0..3 for Bios
  2907.     mov    ah,3            ; check port status, std Bios calls
  2908.     int    rs232            ; Bios call
  2909.     test    ah,mdminp        ; data ready?
  2910.     jnz    prtch9            ; nz = yes, get one
  2911. prtch8:    xor    dx,dx            ; return count of zero
  2912.     stc                ; say no data
  2913.     ret
  2914. prtch9:    mov    ah,2            ; receive a char into al
  2915.     int    rs232            ; Bios call
  2916.     test    ah,8ch            ; timeout, framing error, parity error?
  2917.     jnz    prtch8            ; nz = error, no char
  2918.                     ; single char read final filter    
  2919. prtch10:test    flowcnt,1        ; using XON/XOFF flow control?
  2920.     jz    prtch12            ; z = no
  2921.     cmp    al,flowoff        ; acting on XOFF?
  2922.     jne    prtch11            ; ne = no, go on
  2923.     cmp    xofsnt,0        ; have we sent an outstanding XOFF?
  2924.     jne    prtch8            ; ne = yes, ignore (possible echo)
  2925.     mov    xofrcv,bufon        ; set the flag saying XOFF received
  2926.     xor    dx,dx
  2927.     stc
  2928.     ret
  2929. prtch11:cmp    al,flowon        ; acting on Xon?
  2930.     jne    prtch12            ; ne = no, go on
  2931.     mov    xofrcv,off        ; clear the XOFF received flag
  2932.     xor    dx,dx
  2933.     stc
  2934.     ret                ; no data to return
  2935. prtch12:clc                ; return char in al
  2936.     ret
  2937.  
  2938.                     ; REPLAY, read char from a file
  2939. prtch30:cmp    repflg,2        ; at EOF already?
  2940.     jne    prtch31            ; ne = no
  2941.     stc                ; yes, return with no char
  2942.     ret
  2943. prtch31:push    bx
  2944.     push    cx
  2945.     xor    dx,dx
  2946.     test    xofsnt,usron        ; user level xoff sent?
  2947.     jz    prtch32            ; z = no
  2948.     pop    cx            ; suppress reading here
  2949.     pop    bx
  2950.     stc                ; return with no char
  2951.     ret
  2952. prtch32:cmp    tekflg,0        ; doing Tek plots?
  2953.     jne    prtch33            ; ne = yes, do not insert pauses
  2954.     mov    ax,100
  2955.     mov    bx,1
  2956.     jmp    $+2            ; flush lookahead buffer
  2957.     div    bx            ; burn some cpu cycles
  2958.     div    bx            ; because a 1 ms wait is too long
  2959.     div    bx
  2960.     div    bx
  2961. prtch33:mov    ah,readf2
  2962.     mov    bx,diskio.handle    ; file handle
  2963.     mov    cx,1            ; read one char
  2964.     mov    dx,offset decbuf    ; to this buffer
  2965.     int    dos
  2966.     jc    prtch34            ; c = read failure
  2967.     cmp    ax,cx            ; read the byte?
  2968.     jne    prtch34            ; ne = no
  2969.     pop    cx
  2970.     pop    bx
  2971.     mov    al,decbuf        ; get the char into al
  2972.     mov    dx,1            ; external char count
  2973.     clc
  2974.     ret                ; return it
  2975. prtch34:call    beep
  2976.     mov    ax,40            ; wait 40 millisec
  2977.     call    pcwait
  2978.     call    beep
  2979.     mov    repflg,2        ; say at EOF
  2980.     pop    cx
  2981.     pop    bx
  2982.     stc                ; say no char
  2983.     ret
  2984. PRTCHR  ENDP
  2985.  
  2986. ; DECnet receive routine
  2987. DECRCV    PROC    NEAR
  2988.     test    nettype,declat        ; LAT interface?
  2989.     jz    decrcv1            ; z = not LAT
  2990.     mov    dx,lathand
  2991.     or    dx,dx            ; invalid handle?
  2992.     jz    decrcv1            ; z = yes, try CTERM
  2993.     mov    dh,0ffh
  2994.     mov    ah,latread        ; read char via LAT into AL
  2995.     int    latint
  2996.     test    ah,80h            ; char available?
  2997.     jz    decrcv2            ; z = yes
  2998. ; non-SCB status check, slower and much safer
  2999.     mov    ah,latstat        ; get status
  3000.     mov    dx,lathand
  3001.     mov    dh,0ffh
  3002.     int    latint
  3003.     test    ah,4            ; session not active?
  3004.     jnz    decrcv4            ; nz = yes, no valid session
  3005.     stc                ; return no char
  3006.     ret
  3007. ; end alterntive code
  3008.  
  3009. ;    push    es
  3010. ;    push     bx
  3011. ;    les    bx,latscbptr
  3012. ;    test    es:[bx].sstatus,18h    ; status: stop slot or circuit failure
  3013. ;    pop    bx
  3014. ;    pop    es
  3015. ;    jnz    decrcv4            ; nz = yes, no valid session
  3016. ;    stc                ; return no char
  3017. ;    ret
  3018.  
  3019. decrcv1:test    nettype,decnet        ; is CTERM active?
  3020.     jz    decrcv4            ; z = no
  3021.     mov    dx,decneth        ; handle
  3022.     or    dx,dx            ; legal?
  3023.     jz    decrcv4            ; z = no
  3024.     mov    ax,dcstat        ; CTERM status
  3025.     int    decint
  3026.     test    ah,0c0h            ; no session, DECnet error?
  3027.     jnz    decrcv4            ; nz = yes, stop here
  3028. ;    test    ah,1            ; data available?
  3029. ;    jz    decrcv5            ; z = no
  3030. ; data available test fails under flow control, maybe a Cterm bug.  jrd
  3031.     mov    ax,dread        ; read char via CTERM
  3032.     int    decint
  3033.     test    ah,80h            ; char received?
  3034.     jnz    decrcv5            ; nz = no
  3035. decrcv2:jmp    prtch10            ; use common completion code
  3036.  
  3037. decrcv4:call    nethangup
  3038.     test    flags.remflg,dserver    ; server mode?
  3039.     jz    decrcv5            ; z = no
  3040.     call    serini            ; reinitialize it for new session
  3041. decrcv5:stc                ; say failure to receive
  3042.     ret
  3043. DECRCV    ENDP
  3044.  
  3045. ; NetBios Receive packet routine. If a new packet has been received unpack
  3046. ; the data and request a new one with no-wait option. If a receive request is
  3047. ; still outstanding just return with no new data.
  3048. ; Return carry clear if success. If failure, reset serial port (Server mode
  3049. ; reinits serial port) and return carry set. No entry setup needed.
  3050. RECEIVE PROC    NEAR            ; receive network session pkt
  3051.     cmp    pcnet,1            ; net ready yet?
  3052.     jbe    receiv3            ; be = no, declare a broken session
  3053.     cmp    rposted,1        ; is a request outstanding now?
  3054.     je    receiv4            ; e = yes (1), don't do another
  3055.     jb    receiv1            ; b = no (0), do one now
  3056.     call    receiv2            ; have new pkt, unpack, do new recv
  3057.     jnc    receiv1            ; nc = success
  3058.     ret                ; else return carry set
  3059.  
  3060. receiv1:mov    rposted,1        ; say posting a receive now
  3061.     mov    rcv.scb_length,nbuflen    ; length of input buffer  
  3062.     mov    rcv.scb_cmd,nreceive+nowait   ; receive, no wait
  3063.     push    bx
  3064.     mov    bx,offset rcv        ; setup pointer to scb
  3065.     call    session
  3066.     pop    bx
  3067.     ret                
  3068.  
  3069. receiv2:mov    al,rcv.scb_err        ; returned status
  3070.     or    al,al            ; success?
  3071.     jz    receiv5            ; z = yes, get the data
  3072.     cmp    al,npending        ; pending receive?
  3073.     je    receiv4            ; e = yes
  3074.     cmp    al,6            ; message incomplete?
  3075.     je    receiv5            ; e = yes, get what we have anyway
  3076.     cmp    al,0bh            ; receive cancelled?
  3077.     je    receiv4            ; e = yes
  3078.     cmp    al,18h            ; session ended abnormally?
  3079.     jbe    receiv3            ; e = yes, b = other normal errors
  3080.     mov    ah,prstr
  3081.     mov    dx,offset recmsg    ; give error message
  3082.     int    dos
  3083.     mov    al,rcv.scb_err        ; get error code
  3084.     call    decout            ; show error code
  3085.  
  3086.                     ; Error return
  3087. receiv3:mov    pcnet,1            ; say session is broken
  3088.     mov    rposted,0
  3089.     call    serrst            ; reset serial port
  3090.     test    flags.remflg,dserver    ; server mode?
  3091.     jz    receiv3a        ; z = no
  3092.     call    serini            ; reinitialize it for new session
  3093. receiv3a:stc                ; say failure to receive
  3094.     ret
  3095. receiv4:clc                ; carry clear = success
  3096.     ret
  3097.         ; shared by NetBios, Novell, Opennet, Ungerman Bass, 3ComBAPI
  3098. receiv5:push    bx            ; new packet has been received
  3099.     push    cx            ; copy contents to circ buf source
  3100.     push    dx
  3101.     push    si
  3102.     mov    dh,flowon
  3103.     mov    dl,flowoff
  3104.     mov    si,rcv.scb_baddr    ; source of text (es:bx is scb ptr)
  3105.     mov    bx,srcpnt        ; address of destination buffer slot
  3106. receiv6:mov    cx,rcv.scb_length    ; get remaining returned byte count
  3107.     jcxz    receiv13        ; z = nothing there
  3108.     mov    ax,offset source+bufsiz ; end of destination buffer+1
  3109.     sub    ax,bx            ; space remaining at end of buffer
  3110.     jns    receiv7            ; should never be negative
  3111.     neg    ax            ; but if so invert
  3112. receiv7:cmp    ax,cx            ; buffer ending vs incoming byte count
  3113.     jge    receiv8            ; ge = enough for this pass
  3114.     mov    cx,ax            ; limit this pass to end of the buffer
  3115. receiv8:sub    rcv.scb_length,cx    ; deduct chars done in this pass
  3116.     add    count,cx        ; add them to the count
  3117.     cld                ; inner loop "block" transfer
  3118.     test    flowcnt,1        ; doing XNO/XOFF flow control?
  3119.     jz    receiv20        ; z = no
  3120. receiv9:lodsb                ; get byte from rcvbuf to al
  3121.     mov    ah,al            ; get copy of character
  3122.     and    ah,parmsk        ; strip parity, if any, before testing
  3123.     cmp    ah,dl            ; acting on Xoff?
  3124.     jne    receiv10        ; ne = no
  3125.     cmp    xofsnt,0        ; have we sent an XOFF?
  3126.     jne    receiv12        ; ne = yes, ignore this XOFF char
  3127.     mov    xofrcv,bufon        ; set flag saying buffer XOFF received
  3128.     jmp    short receiv12        ;  and skip this character
  3129. receiv10:cmp    ah,dh            ; acting on Xon?
  3130.     jne    receiv11        ; ne = no, go on
  3131.     mov    xofrcv,off        ; clear the XOFF received flag
  3132.     jmp    short receiv12        ;  and skip this character
  3133. receiv11:mov    [bx],al            ; store new char in buffer "source"
  3134.     inc    bx
  3135. receiv12:loop    receiv9            ; bottom of inner loop
  3136.     jmp    short receiv22
  3137. receiv20:push    es            ; no flow control, just do copy
  3138.     push    di
  3139.     mov    ax,ds
  3140.     mov    es,ax
  3141.     mov    di,bx            ; destination
  3142.     shr    cx,1
  3143.     jnc    receiv21
  3144.     movsb
  3145. receiv21:rep    movsw            ; do quick copy
  3146.     mov    bx,di            ; update destination pointer
  3147.     pop    di
  3148.     pop    es
  3149. receiv22:                ; update buffer pointer for wrapping
  3150.     cmp    bx,offset source+bufsiz    ; pointing beyond end of buffer?
  3151.     jb    receiv6            ; b = no, do next pass
  3152.     mov    bx,offset source    ; wrap pointer, modulo bufsiz
  3153.     jmp    short receiv6        ; do next pass
  3154.  
  3155. receiv13:mov    srcpnt,bx        ; update pointer to next free slot
  3156.     cmp    count,bufsiz        ; count more that buffer size?
  3157.     jbe    receiv14        ; be = no
  3158.     mov    count,bufsiz        ; limit to bufsiz (tells the truth)
  3159. receiv14:mov    rposted,0        ; clear interlock flag
  3160.     pop    si
  3161.     pop    dx
  3162.     pop    cx
  3163.     pop    bx
  3164.     clc
  3165.     ret
  3166. RECEIVE    ENDP
  3167.  
  3168. ; NetBios Receive post processing interrupt routine.
  3169. ; Sets rposted interlock flag
  3170. RPOST    PROC    NEAR        ; NetBios receive post interrupt routine
  3171.     push    ds
  3172.     push    ax
  3173.     mov    ax,data            ; reestablish data segment
  3174.     mov    ds,ax
  3175.     mov    rposted,2        ; set interlock flag to completed
  3176.     pop    ax
  3177.     pop    ds
  3178.     iret                ; return from interrupt
  3179. RPOST    endp
  3180.  
  3181. ; TES block mode receive, uses receiv5 to process results
  3182. TESRCV    proc    near
  3183.     push    di
  3184.     push    cx
  3185.     push    dx
  3186.     push    es
  3187.     mov    ax,data
  3188.     mov    es,ax            ; es:di will point to rcvbuf
  3189.     mov    di,offset rcvbuf
  3190.     mov    cx,nbuflen        ; buffer length
  3191.     mov    dx,tesport        ; operational port
  3192.     mov    ah,tesbread        ; block read
  3193.     int    rs232
  3194.     jcxz    tesrcv2            ; z = no characters read
  3195.     mov    rcv.scb_length,cx    ; prepare for receive call
  3196.     call    receiv5            ; process rcvbuf
  3197. tesrcv2:pop    es
  3198.     pop    dx
  3199.     pop    cx
  3200.     pop    di
  3201.     ret
  3202. TESRCV    endp
  3203.  
  3204. ; Ungermann-Bass NETCI port receive characters routine.  Receive one or more
  3205. ; characters.  Calls the receiv5 routine to transfer character to main source
  3206. ; circular buffer.  Return carry clear if success. 
  3207. UBRECV    PROC    near
  3208.     push    bx
  3209.     push    cx
  3210.     push    es
  3211.     mov    ax,data
  3212.     mov    es,ax            ; es:bx will point to rcvbuf
  3213.     mov    bx,offset rcvbuf
  3214.     mov    cx,nbuflen        ; buffer length
  3215. ubrecv2:test    nettype,bapi+tcpnet    ; 3Com BAPI or TCP Telnet interface?
  3216.     jz    ubrecv2a        ; z = no
  3217.     mov    ah,bapiread
  3218.     xor    dh,dh            ; session 0
  3219.     int    bapiint
  3220.     cmp    ah,3            ; status, no session and above
  3221.     jb    ubrecv3            ; b = no, successful?
  3222.     call    nethangup        ; broken connection, terminate it
  3223.     stc
  3224.     jmp    short ubrec1
  3225. ubrecv2a:test    nettype,telapi        ; Novell TELAPI?
  3226.     jz    ubrecv2c        ; z = no, use Int 6Bh kind
  3227.     cmp    pcnet,2            ; port going?
  3228.     jb    ubrec1            ; b = no
  3229.     push    si
  3230.     push    bx
  3231.     mov    si,bx            ; use es:si for buffer address
  3232.     mov    bx,telses        ; session number
  3233.     mov    ah,telread
  3234.     int    rs232
  3235.     pop    bx
  3236.     pop    si
  3237.     xchg    ax,cx            ; byte count returned in AX
  3238.     jcxz    ubrecv2b        ; z = connection broken
  3239.     or    cx,cx
  3240.     jns    ubrecv3            ; ns = no error
  3241.     cmp    cx,-35            ; status of no data?
  3242.     jne    ubrecv2b        ; ne = no
  3243.     xor    cx,cx            ; mimic no data
  3244.     clc
  3245.     jmp    short ubrec1
  3246. ubrecv2b:call    nethangup        ; clear the connection anyway
  3247.     xor    cx,cx            ; say no data
  3248.     stc
  3249.     jmp    short ubrec1
  3250.  
  3251. ubrecv2c:test    nettype,netone        ; UB?
  3252.     jz    ubrec1            ; z = no, do nothing
  3253.     mov    ax, nciread        ; function 1 (receive) port 0     [ohl]
  3254.     int    netci            ; get characters         [ohl]
  3255. ubrecv3:stc
  3256.     jcxz    ubrec1            ; cx = z = nothing to do
  3257. ubrecv3a:mov    rcv.scb_length, cx    ; prepare for rpost call     [ohl]
  3258.     call    receiv5            ; process buffer
  3259.     clc
  3260. ubrec1:    pop    es
  3261.     pop    cx
  3262.     pop    bx
  3263.     ret
  3264. UBRECV    ENDP
  3265.  
  3266. ; Put the char in AH to the serial port, assumimg the port is active.
  3267. ; Returns carry clear if success, else carry set.
  3268. ; 16 May 1987 Add entry point OUTCH2 for non-flow controlled sending to
  3269. ; prevent confusion of flow control logic at top of outchr; used by receiver
  3270. ; buffer high/low water mark flow control code. [jrd]
  3271. OUTCHR    PROC    NEAR
  3272.     cmp    quechar,0        ; char queued for transmission?
  3273.     je    outch0            ; e = no, no XOFF queued
  3274.     xchg    ah,quechar        ; save current char
  3275.     cmp    ah,flowoff        ; really XOFF?
  3276.     jne    outch0a            ; ne = no
  3277.     mov    xofsnt,bufon           ; we are senting XOFF at buffer level
  3278. outch0a:call    outch2            ; send queued char (XOFF usually)
  3279.     xor    ah,ah            ; replacement for queued char, none
  3280.     xchg    ah,quechar        ; recover current char, send it
  3281. outch0:    test    flowcnt,1        ; doing XON/XOFF flow control?
  3282.     jz    outch2            ; z = no, just continue
  3283.     cmp    ah,flowoff        ; sending xoff?
  3284.     jne    outch1            ; ne = no
  3285.     mov    xofsnt,usron        ; indicate user level xoff being sent
  3286.     jmp    short outch1b
  3287. outch1:    and    xofsnt,not usron    ; cancel user level xoff
  3288.     cmp    ah,flowon        ; user sending xon?
  3289.     jne    outch1b            ; ne = no
  3290.     mov    xofsnt,off         ; say an xon has been sent (cancels xoff)
  3291. outch1b:cmp    xofrcv,off        ; Are we being held (xoff received)?
  3292.     je    outch2            ; e = no - it's OK to go on
  3293.     push    cx            ; save reg
  3294.     mov    ch,15            ; 15 sec timeout interval
  3295.     xor    cl,cl            ;  convert to 4 millsec increments
  3296.  
  3297. outch1a:cmp    xofrcv,off        ; are we being held (xoff received)?
  3298.     je    outch1c            ; e = no - it's OK to go on
  3299.     push    ax
  3300.     mov    ax,4            ; 4 millisec wait loop
  3301.     call    pcwait
  3302.     pop    ax
  3303.     loop    outch1a            ; and try it again
  3304.     mov    xofrcv,off        ; timed out, force it off
  3305.     cmp    ttyact,0        ; in Connect mode?
  3306.     je    outch1c            ; e = no
  3307.     push    ax            ; save char around the call
  3308.     call    beep            ; let user know we are xoff-ed
  3309.     pop    ax            ;  but are sending anyway
  3310. outch1c:pop    cx            ; end of flow control section
  3311.              ; OUTCH2 is entry point for sending without flow control
  3312. OUTCH2:    mov    al,ah            ; Parity routine works on AL
  3313.     call    dopar            ; Set parity appropriately
  3314.     mov    ah,al            ; Don't overwrite character with status
  3315.     cmp    repflg,0        ; doing REPLAY from a file?
  3316.     je    outch3            ; e = no
  3317.     and    al,7fh            ; strip parity
  3318.     cmp    al,'C'-40h        ; Control-C? (to exit playback mode)
  3319.     je    outch2a            ; e = yes, return failure
  3320.     clc                ; return success, send nothing
  3321.     ret
  3322. outch2a:stc                ; failure, to exit playback mode
  3323.     ret
  3324. outch3:    cmp    flags.comflg,'0'    ; Bios?
  3325.     jb    outch3a            ; b = no, UART
  3326.     cmp    flags.comflg,'4'    ; Bios?
  3327.     jbe    outch3e            ; be = yes
  3328.     jmp    outch8            ; else try networks
  3329. outch3e:jmp    outch6            ; do Bios routine
  3330.  
  3331. outch3a:push    cx            ; Bios
  3332.     push    dx
  3333.     mov    dx,modem.mddat
  3334.     add    dx,4            ; modem control reg 3fch
  3335.     cmp    dupflg,0        ; full duplex?
  3336.     jne    outch3b            ; ne = no, half
  3337.     test    flowcnt,2        ; using RTS to control incoming chars?
  3338.     jz    outch3d            ; z = no
  3339.     mov    cx,8000            ; ~10 seconds worth of waiting on CTS
  3340.     add    dx,2            ; modem status reg 3feh
  3341.     jmp    short outch3c        ; do CTS test/waiting
  3342.                     ; Half Duplex here
  3343. outch3b:in    al,dx            ; modem control reg 3fch
  3344.     or    al,2            ; assert RTS for hardware transmit
  3345.     jmp    $+2
  3346.     out    dx,al
  3347.     add    dx,2            ; modem status register 3feh
  3348.     jmp    $+2
  3349.     in    al,dx            ; get DSR status
  3350.     test    al,20h            ; ignore CTS if DSR is not asserted
  3351.     jz    outch3d            ; z = DSR not asserted
  3352.     mov    cx,8000            ; ~10 seconds worth of waiting on CTS
  3353.                     ; Half Duplex and RTS/CTS flow cont.
  3354. outch3c:in    al,dx            ; wait on CTS (ah has output char)
  3355.     test    al,10h            ; is CTS asserted? (dx = 3feh)
  3356.     jnz    outch3d            ; nz = yes
  3357.     push    ax            ; preserve char in ah
  3358.     mov    ax,1            ; wait one millisec
  3359.     call    pcwait
  3360.     pop    ax
  3361.     loop    outch3c            ; test again
  3362.     push    ax
  3363.     call    beep            ; timeout, make non-fatal
  3364.     pop    ax            ; continue to send the char
  3365.  
  3366. outch3d:push    bx
  3367.     mov    bx,portval
  3368.     cmp    [bx].baud,Bsplit    ; split-speed mode?
  3369.     pop    bx
  3370.     jne    outch3f            ; ne = no
  3371.     mov     al,ah                   ; [pslms]
  3372.         call    out75b            ; do split speed sending at 75 baud
  3373.         pop     dx
  3374.         pop     cx
  3375.     ret                ; out75b sets/clears carry bit
  3376.  
  3377. outch3f:xor    cx,cx
  3378.     mov    dx,modem.mdstat        ; get port status
  3379.     in    al,dx
  3380.     test    al,20H            ; Transmitter (THRE) ready?
  3381.     jnz    outch4            ; nz = yes
  3382.     jmp    $+2            ; use time, prevent overdriving UART
  3383.     jmp    $+2
  3384.     loop    outch3f
  3385.     jmp    short outch5        ; Timeout
  3386. outch4:    mov    al,ah            ; Now send it out
  3387.     mov    dx,modem.mddat        ; use a little time
  3388.     jmp    $+2
  3389.     out    dx,al
  3390.     cmp    dupflg,0        ; full duplex?
  3391.     je    outch4a            ; e = yes
  3392.     cmp    al,trans.seol        ; End of Line char?
  3393.     jne    outch4a            ; ne = no
  3394.     xor    cx,cx            ; loop counter
  3395. outch4b:mov    dx,modem.mdstat        ; modem line status reg
  3396.     in    al,dx            ; read transmitter shift reg empty bit
  3397.     jmp    $+2
  3398.     jmp    $+2
  3399.     jmp    $+2            ; wait for char to be sent
  3400.     test    al,40h            ; is it empty?
  3401.     loopz    outch4b            ; z = no, not yet
  3402.     mov    dx,modem.mddat
  3403.     add    dx,4            ; modem control reg 3fch
  3404.     in    al,dx
  3405.     and    al,not 2        ; unassert RTS
  3406.     jmp    $+2
  3407.     out    dx,al
  3408. outch4a:pop    dx            ; exit success
  3409.     pop    cx
  3410.     clc
  3411.     ret
  3412. outch5:    call    beep
  3413.     pop    dx            ; exit failure
  3414.     pop    cx
  3415.     stc
  3416.     ret
  3417.                     ; finish up for Bios calls
  3418. outch6:    push    cx            ; find current port
  3419.     mov    cx,5            ; retry counter
  3420.     push    dx
  3421.     xor    dx,dx            ; assume port 1
  3422.     mov    dl,flags.comflg        ; get port number (1..4)
  3423.     or    dl,dl            ; zero (no such port)?
  3424.     jz    outch5            ; z = yes, don't access it
  3425.     and    dl,7            ; use lower three bits
  3426.     dec    dl            ; address ports as 0..3 for Bios
  3427.     mov    al,ah            ; now send it out
  3428. outch6a:push    ax            ; save char
  3429.     mov    ah,1            ; send char
  3430.     int    rs232            ; bios send
  3431.     shl    ah,1            ; set carry if failure
  3432.     pop    ax            ; recover char
  3433.     jnc    outch6b            ; nc = success
  3434.     push    ax
  3435.     mov    ax,60            ; wait 60 ms
  3436.     call    pcwait            ; this must preserve cx and dx
  3437.     pop    ax            ; recover char
  3438.     loop    outch6a            ; try again
  3439.     stc                ; fail through here
  3440. outch6b:pop    dx
  3441.     pop    cx
  3442.     ret                ; c set = failure, else success
  3443.  
  3444. outch8:                ; Network sending, buffered and single char
  3445.     cmp    flags.comflg,'D'    ; DECnet?
  3446.     jne    outch8a            ; ne = no
  3447.     jmp    outch14            ; e = yes
  3448. outch8a:push    bx
  3449.     mov    bx,xmtcnt        ; count of chars in buffer
  3450.     mov    xmtbufx[bx],ah        ; put char in buffer
  3451.     pop    bx
  3452.     inc    xmtcnt            ; count of items in this buffer
  3453.     cmp    ah,CR            ; carriage return?
  3454.     jne    outch8e            ; ne = no
  3455.     test    nettype,tcpnet        ; Telnet?
  3456.     jz    outch8e            ; z = no
  3457.     push    bx
  3458.     mov    bx,portval        
  3459.     cmp    [bx].ecoflg,0        ; Telnet local echo (line mode)?
  3460.     pop    bx
  3461.     je    outch8e            ; e = no
  3462.     cmp    xmtcnt,length xmtbuf    ; is buffer full?
  3463.     jae    outch8d            ; ae = yes, take special setps
  3464. outch8c:push    bx
  3465.     mov    bx,xmtcnt
  3466.     mov    xmtbufx[bx],LF        ; append LF, send CR/LF as a unit
  3467.     pop    bx
  3468.     inc    xmtcnt
  3469.     jmp    short outch9        ; send buffer now
  3470. outch8d:call    ubsend            ; send what we have now
  3471.     jmp    short outch8c        ; jump up and add char
  3472.  
  3473. outch8e:cmp    xmtcnt,length xmtbuf    ; is buffer full now?
  3474.     jae    outch9            ; ae = buffer is full, send it now
  3475.     cmp    ah,trans.seol        ; end of packet?
  3476.     je    outch9            ; e = yes, send buffer
  3477.     test    flowcnt,1        ; using XON/XOFF flow control?
  3478.     jz    outch8b            ; z = no
  3479.     cmp    ah,flowon        ; flow control?
  3480.     je    outch9            ; e = yes, always expedite
  3481.     cmp    ah,flowoff        ; ditto for flow off
  3482.     je    outch9
  3483. outch8b:cmp    ttyact,0        ; are we in Connect mode?
  3484.     je    outch10            ; e = no, wait for more before sending
  3485. outch9: cmp    flags.comflg,'U'    ; check for UB port     [ohl]
  3486.     je    outch12            ; e = yes         [ohl]
  3487.     cmp    flags.comflg,'W'    ; Novell NACS?
  3488.     je    outch12            ; e = yes
  3489.     cmp    flags.comflg,'C'    ; 3Com BAPI
  3490.     je    outch12            ; e = yes
  3491.     cmp    flags.comflg,'E'    ; EBIOS?
  3492.     je    outch13            ; e = yes
  3493.     cmp    flags.comflg,'T'    ; Novell TELAPI?
  3494.     je    outch12
  3495.     cmp    flags.comflg,'t'    ; TCP/IP Telnet?
  3496.     je    outch12            ; e = yes
  3497.     cmp    flags.comflg,'I'    ; TES?
  3498.     je    outch11            ; e = yes
  3499.     jmp    send            ; NetBios network send routine
  3500.  
  3501. outch10:clc                ; good exit
  3502.     ret
  3503. outch11:jmp    tessnd            ; TES network send
  3504. outch12:jmp    ubsend            ; UB/Novell network send
  3505.  
  3506. outch13:push    si            ; EBIOS send
  3507.     mov    si,offset xmtbufx
  3508.     mov    cx,xmtcnt        ; buffer count
  3509.     jcxz    outch13b        ; z = nothing to send
  3510. outch13a:cld
  3511.     lodsb
  3512.     mov    ah,ebsend        ; EBIOS send a char from AL
  3513.     push    dx
  3514.     mov    dx,ebport        ; port 0..3, do here to waste time
  3515.     int    rs232            ; bios send
  3516.     pop    dx
  3517.     shl    ah,1            ; put status high bit into carry
  3518.     jc    outch13b        ; c = failure
  3519.     loop    outch13a
  3520. outch13b:mov    xmtcnt,0
  3521.     pop    si
  3522.     ret                ; c set = failure, else success
  3523.  
  3524. outch14:test    nettype,declat        ; LAT?
  3525.     jz    outch14a        ; z = no, use CTERM
  3526.     mov    cx,10            ; retry counter
  3527.     mov    byte ptr temp,ah    ; outgoing char
  3528. outch14d:mov    dx,lathand        ; LAT handle
  3529.     or    dx,dx            ; legal handle?
  3530.     jz    outch14c        ; z = invalid handle
  3531.     push    cx
  3532.     mov    dh,0ffh
  3533.     mov    al,byte ptr temp
  3534.     mov    ah,latsend        ; LAT send byte
  3535.     int    latint
  3536.     pop    cx
  3537.     or    ah,ah            ; status
  3538.     jnz    outch14e        ; nz = failed, check
  3539.     clc
  3540.     ret
  3541. outch14e:mov    ah,latstat        ; status call
  3542.     mov    dx,lathand        ; handle
  3543.     mov    dh,0ffh
  3544.     int    latint
  3545.     test    ah,4            ; session active?
  3546.     jnz    outch14c        ; nz = no, fail
  3547.     mov    ax,10            ; wait 10 millisecs
  3548.     call    pcwait
  3549.     loop    outch14d        ; retry
  3550.     jmp    short outch14c        ; fail outright
  3551.  
  3552. outch14a:mov    dx,decneth        ; DECnet, handle
  3553.     or    dx,dx            ; legal handle?
  3554.     jz    outch14c        ; z = invalid handle
  3555.     push    bx            ; CTERM
  3556.     mov    bl,ah            ; char to be sent
  3557.     mov    ax,dsend        ; send byte in bl
  3558.     int    decint
  3559.     pop    bx
  3560. outch14b:rcl    ah,1            ; status 80h bit, did char get sent?
  3561.     jnc    outch15            ; nc = success
  3562. outch14c:call    nethangup        ; failure
  3563.     stc
  3564. outch15:ret
  3565. OUTCHR    ENDP
  3566.  
  3567. ; Software uart that generates output rate of 75 baud independently of
  3568. ; 8250 baudrate; use with V.23 split speed modems.
  3569. ; This routine outputs a character in 8,<parity>,1 format only.
  3570. ; To generate good bit timing, latency is to be kept low; now set for max
  3571. ; 12% bit distortion and 1.2% speed deviation (about the same as the input
  3572. ; stage of a HW-uart), which requires latency < 3ms (i e the same as 8250
  3573. ;  requires for receive in 9600 baud)
  3574. ; Creator Dan Norstedt 1987. Implemented 18 Feb 1988 by [pslms].
  3575. out75b    proc    near
  3576.     mov    timeract,1    ; say we are allocating the timer chip
  3577.     push    bx
  3578.     push    cx
  3579.     push    dx
  3580.     xchg    ax,bx           ; save char to output
  3581.         mov     bh,1            ; prepare output char
  3582.         mov     cx,cnt75b       ; maximum end count
  3583. out75b1:call    read_timer2     ; save previous end count in CX, read timer
  3584.                                 ;  test for timer still decrementing ?
  3585.         jb      out75b1         ; b = yes, wait (for a maximum of 1 bit)
  3586.         mov     al,0b4h         ; set up counter 2 to mode 2, load LSB+MSB
  3587.         out     timercmd,al     ; set mode 2 = rate generator
  3588.         jmp     $+2
  3589.         mov     ax,cnt75b*4+cnt75b*4+cnt75b*2-precomp  ; set start point
  3590.         out     timer2data,al   ; output LSB
  3591.         jmp     $+2
  3592.         xchg    cx,ax           ; save value in CX for compare in READ_TIMER2
  3593.         mov     al,ch           ; output MSB
  3594.         cli                     ; timer starts counting on next instr, make
  3595.         out     timer2data,al   ;  sure it's not to far of from start bit
  3596.         in      al,ppi_port     ; get Port B contents
  3597.         jmp     $+2
  3598.         and     al,0fch         ; mask speaker and gate 2 bits
  3599.         inc     ax
  3600.         out     ppi_port,al     ; set speaker off and gate 2 on
  3601.         mov     al,-1
  3602.         out     timer2data,al   ; set counter wraparound to 0FFFFH
  3603.         jmp     $+2
  3604.         out     timer2data,al
  3605.         mov     bp,cnt75b*4+cnt75b*4+cnt75b ; set timer value for next bit
  3606.         mov     dx,modem.mddat  ; get com port address
  3607.         add     dx,3            ; address of it's line control register
  3608.         in      al,dx           ; get port status
  3609.         jmp     $+2
  3610. out75b2:or      al,brkbit       ; set line to space (by using break bit)
  3611. out75b3:out     dx,al           ; once start bit is out, we may reenable
  3612.         sti                     ;  without getting extra jitter
  3613. out75b4:call    read_timer2
  3614.         jns     out75b5         ; ns = timer doesn't seem to run
  3615.         cmp     ax,bp           ; time for next bit?
  3616.         jns     out75b4         ; ns = no, wait
  3617.         sub     bp,cnt75b       ; yes, step time to next event
  3618.         in      al,dx           ; get line control register
  3619.         and     al,0bfh         ; remove break bit
  3620.         shr     bx,1            ; carry for mark bit, none for space
  3621.         jnc     out75b2         ; nc = it was a space (we know BX is non-zero)
  3622.         jnz     out75b3         ; mark, and not the last one
  3623.         jmp     $+2
  3624.         out     dx,al           ; last, start to send stop bit
  3625.     pop    dx
  3626.     pop    cx
  3627.         pop     bx
  3628.     mov    timeract,0    ; say we are finished with the timer chip
  3629.     cmp    quechar,0    ; any char queued to be sent?
  3630.     je    out75b6        ; e = no
  3631.     call    outchr        ; yes, send it now
  3632. out75b6:clc
  3633.     ret
  3634. out75b5:in      al,dx           ; timer doesn't function properly,
  3635.         and     al,0bfh         ;  restore com port and return error
  3636.         out     dx,al
  3637.     mov    timeract,0    ; say we are finished with the timer chip
  3638.     pop    dx
  3639.     pop    cx
  3640.     pop    bx
  3641.     stc
  3642.         ret
  3643. out75b    endp
  3644.      
  3645. read_timer2    proc    near
  3646.         mov     al,80h          ; Freeze timer 2
  3647.         out     timercmd,al
  3648.         jmp     $+2
  3649.         in      al,timer2data   ; Get LSB
  3650.         jmp     $+2
  3651.         mov     ah,al
  3652.         in      al,timer2data   ; Get MSB
  3653.         xchg    al,ah           ; Get LSB and MSB right
  3654.         cmp     ax,cx           ; Compare to previous sample
  3655.         mov     cx,ax           ; Replace previous sample with current
  3656.         ret
  3657. read_timer2 endp
  3658.  
  3659. ; NetBios Send packet routine. Send xmt scb with no-wait option. Waits
  3660. ; up to 6 seconds for current Send to complete before emitting new Send.
  3661. ; Failure to Send resets serial port (Server mode allows reiniting of serial
  3662. ; port). Returns carry clear for success, carry set for failure.
  3663. ; Enter with xmtcnt holding length of data in xmtbuf to be sent.
  3664. SEND    PROC    NEAR            ; Network. Send session packet
  3665.     cmp    pcnet,1            ; network ready yet?
  3666.     ja    send0b            ; a = net is operational
  3667.     je    send0c            ; e = net but no session, fail
  3668.     jmp    send3a            ; no net, fail
  3669. send0c:    jmp    send3            ; net but no session
  3670. send0b:    cmp    sposted,0        ; is a send outstanding now?
  3671.     je    send1            ; e = no, go ahead
  3672.     push    cx            ; Timed test for old send being done
  3673.     mov    ch,trans.rtime        ; receive timeout other side wants
  3674.     mov    cl,80h            ; plus half a second
  3675.     shl    cx,1            ; sending timeout * 512
  3676. send0:    cmp    sposted,0        ; is a send outstanding now?
  3677.     je    send0a            ; e = no, clean up and do send
  3678.     push    cx            ; save cx
  3679.     push    ax            ; and ax
  3680.     mov    ax,2            ; wait 2 milliseconds
  3681.     call    pcwait            ;  between retests
  3682.     pop    ax
  3683.     pop    cx            ; loop counter
  3684.     loop    send0            ; repeat test
  3685.     pop    cx            ; recover cx
  3686.     jmp    send3a            ; get here on timeout, can't send
  3687. send0a:    pop    cx            ; recover cx and proceed to send
  3688.  
  3689. send1:    cmp    xmtcnt,0        ; number of items to send
  3690.     jne    send1a            ; ne = some
  3691.     clc                ; else don't send null packets
  3692.     ret
  3693. send1a:    push    bx            ; save these regs
  3694.     push    cx
  3695.     push    si
  3696.     push    di
  3697.     push    es
  3698.     push    ds
  3699.     pop    es            ; set es to data segment
  3700.     mov    si,offset xmtbufx    ; external buffer
  3701.     mov    di,offset xmtbuf    ; copy for network packets
  3702.     mov    cx,xmtcnt        ; buffer length
  3703.     mov    xmt.scb_length,cx    ; tell buffer length
  3704.     shr    cx,1            ; divide by two (words), set carry
  3705.     jnc    send2            ; nc = even number of bytes
  3706.     movsb                ; do single move
  3707. send2:    rep    movsw            ; copy the data
  3708.     pop    es
  3709.     pop    di
  3710.     pop    si
  3711.     pop    cx
  3712.     mov    xmtcnt,0        ; say xmtbufx is available again
  3713.     mov    xmt.scb_cmd,nsend+nowait ; send, don't wait for completion
  3714.     mov    sposted,1        ; say send posted
  3715.     mov    bx,offset xmt        ; set pointer to scb
  3716.     call    session
  3717.     pop    bx            ; recover pointer to scb
  3718.                     ; success or failure?
  3719.     cmp    xmt.scb_err,0        ; good return?
  3720.     je    send4            ; e = yes
  3721.     cmp    xmt.scb_err,npending    ; pending?
  3722.     je    send4            ; e = yes
  3723.     cmp    xmt.scb_err,18h        ; session ended abnormally?
  3724.     jbe    send3            ; e = yes, b = other normal errors
  3725.     push    ax
  3726.     push    dx            ; another kind of error, show message
  3727.     mov    ah,prstr
  3728.     mov    dx,offset sndmsg    ; say send failed
  3729.     int    dos
  3730.     mov    al,xmt.scb_err        ; show error code
  3731.     call    decout
  3732.     pop    dx
  3733.     pop    ax
  3734.                     ; Error return
  3735. send3:    mov    pcnet,1            ; say session is broken
  3736.     call    serrst            ; reset serial port
  3737.     test    flags.remflg,dserver    ; server mode?
  3738.     jz    send3a            ; z = no
  3739.     call    nethangup        ; Server: purge old NAKs etc
  3740. send3a:    call    serini            ; reinitialize it for new session
  3741.     stc                ; set carry for failure to send
  3742.     ret
  3743. send4:    clc
  3744.     ret
  3745. SEND    ENDP
  3746.  
  3747. ; NetBios Send packet completion interrupt routine. At entry CS is our
  3748. ; code segment, es:bx points to scb, netbios stack, interrupts are off.
  3749. SPOST    PROC    NEAR            ; post routine for Send packets
  3750.     push    ds
  3751.     push    ax
  3752.     mov    ax,data
  3753.     mov    ds,ax
  3754.     mov    sposted,0        ; clear send interlock
  3755.     pop    ax
  3756.     pop    ds
  3757.     iret
  3758. SPOST    ENDP    
  3759.  
  3760. ; TES block send
  3761. TESSND    proc    near
  3762.     push    ax
  3763.     push    cx
  3764.     push    dx
  3765.     push    di
  3766.     push    es
  3767.     mov    cx,xmtcnt        ; number of chars
  3768.     jcxz    tessnd4            ; don't send zero chars
  3769.     mov    di,offset xmtbufx    ; buffer address in es:di
  3770.     mov    ax,data
  3771.     mov    es,ax
  3772. tessnd1:mov    temp,0            ; retry counter
  3773. tessnd2:mov    ah,tesbwrite        ; block write
  3774.     mov    dx,tesport        ; operational port
  3775.     int    rs232
  3776.     or    ax,ax            ; number of chars sent, zero?
  3777.     jnz    tessnd3            ; nz = sent some
  3778.     mov    ax,10            ; wait 10ms
  3779.     call    pcwait
  3780.     inc    temp            ; count retry
  3781.     cmp    temp,5            ; done all retries?
  3782.     jb    tessnd2            ; b = no
  3783.     call    nethangup        ; declare failure
  3784.     stc
  3785.     jmp    short tessnd5        ; exit failure
  3786.  
  3787. tessnd3:cmp    ax,cx            ; check that all characters were sent
  3788.     je    tessnd4            ; e = yes
  3789.     add    di,ax            ; point to remaining chars
  3790.     sub    cx,ax            ; count of remaining characters
  3791.     mov    xmtcnt,cx        ; need count in xmtcnt too
  3792.     jmp    short tessnd1        ; try again to send
  3793. tessnd4:clc                ; success, need failure case too
  3794. tessnd5:mov    xmtcnt,0
  3795.     pop    es
  3796.     pop    di
  3797.     pop    dx
  3798.     pop    cx
  3799.     pop    ax
  3800.     ret
  3801. TESSND    endp
  3802.  
  3803. ; Ungermann-Bass NETCI/Novell NASI port send packet routine.
  3804. ; Enter with xmtcnt holding length of data in xmtbuf to be sent.
  3805. ubsend    proc    near
  3806.     push    ax
  3807.     push    bx
  3808.     push    cx
  3809.     push    es
  3810.     mov    cx, xmtcnt        ; number of chars         [ohl]
  3811.     jcxz    ubsend1            ; don't send zero chars         [ohl]
  3812.     mov    bx, offset xmtbufx    ; buffer address in es:bx     [ohl]
  3813.     mov    ax, data
  3814.     mov    es, ax
  3815. ubsend2:test    nettype,bapi+tcpnet    ; 3Com BAPI or TCP Telnet?
  3816.     jz    ubsend2a        ; z = no
  3817.     mov    ah,bapiwrit        ; 3Com block write
  3818.     xor    dh,dh            ; session 0
  3819.     int    bapiint
  3820.     cmp    ah,3            ; status, no session and above
  3821.     jae    ubsend2b        ; ae = no session and above, fail
  3822.     jmp    short ubsend3        ; process data
  3823. ubsend2a:test    nettype,telapi        ; Novell TELAPI?
  3824.     jz    ubsend2c        ; z = no, Int 6Bh kind
  3825.     push    si
  3826.     push    bx            ; preserve buffer offset
  3827. ;;v4    call    telsetline        ; set char/line mode
  3828.     mov    si,bx            ; use es:si for buffer address
  3829.     mov    ah,telwrite
  3830.     mov    bx,telses        ; session number
  3831.     int    rs232
  3832.     pop    bx
  3833.     pop    si
  3834.     mov    cx,ax            ; TELAPI returns sent count in AX
  3835.     or    ax,ax            ; error response (sign bit set)?
  3836.     jns    ubsend3            ; ns = no error
  3837.  
  3838. ubsend2b:call    nethangup        ; failure, hangup the connection
  3839.     pop    es
  3840.     pop    cx
  3841.     pop    bx
  3842.     pop    ax
  3843.     stc                ; failure
  3844.     ret
  3845.  
  3846. ubsend2c:test    nettype,netone        ; UB?
  3847.     jz    ubsend1            ; no, do nothing
  3848.     mov    ax, nciwrit        ; write function, port 0     [ohl]
  3849.     int    netci
  3850. ubsend3:cmp    cx,xmtcnt        ; check that all characters sent [ohl]
  3851.     je    ubsend1            ; e = yes             [ohl]
  3852.     add    bx, cx            ; point to remaining chars     [ohl]
  3853.     sub    xmtcnt,cx        ; count of remaining characters     [ohl]
  3854.     mov    cx,xmtcnt        ; need count in cx too
  3855.     jmp    short ubsend2        ; try again to send         [ohl]
  3856. ubsend1:mov    xmtcnt,0
  3857.     pop    es
  3858.     pop    cx
  3859.     pop    bx
  3860.     pop    ax
  3861.     clc                ; success, need failure case too
  3862.     ret
  3863. ubsend    endp                ;  [ohl] ---
  3864.  
  3865. ; TELAPI, perform telioctl to set transmission line mode of Char or Line
  3866. ; depending on whether in single char (ttyact != 0) or not. Remember state
  3867. ; in telstate.
  3868. telsetline proc    near
  3869. ;    push    cx
  3870. ;    mov    cx,7            ; assume single char mode
  3871. ;    cmp    ttyact,0        ; multichar mode?
  3872. ;    jne    telset2            ; ne = yes
  3873. ;    cmp    xmtcnt,1        ; sending just one char?
  3874. ;    je    telset2            ; e = yes, set Char state
  3875. ;    cmp    trans.seol,CR        ; CR ends packets?
  3876. ;    jne    telset2            ; ne = no, must use Char mode
  3877. ;    inc    cx            ; line mode is Telnet Option 8
  3878. ;telset2:cmp    cx,telstate        ; same as currently set?
  3879. ;    jne    telset3            ; ne = no, change it
  3880. ;    pop    cx
  3881. ;    ret
  3882. ;
  3883. ;telset3:push    bx            ; change line state
  3884. ;    push    es
  3885. ;    mov    si,ds
  3886. ;    mov    es,si
  3887. ;    mov    si,offset teloption    ; es:si = Option data structure
  3888. ;    mov    word ptr [si],0        ; clear the numeric fields
  3889. ;    mov    word ptr [si+2],0
  3890. ;    mov    telstate,cx        ; remember new line state
  3891. ;    cmp    cx,7            ; do Char mode?
  3892. ;    je    telset4            ; e = yes
  3893. ;    mov    word ptr [si],offset temp ; set Line mode
  3894. ;    mov    bx,ds
  3895. ;    mov    word ptr [si+2],bx
  3896. ;    mov    temp,0            ; erase line char, a dummy
  3897. ;telset4:mov    bx,telses        ; session
  3898. ;    mov    ah,telioctl        ; ioctl to do it
  3899. ;    int    rs232
  3900. ;    pop    es
  3901. ;    pop    bx
  3902. ;    pop    cx
  3903.     ret
  3904. telsetline endp
  3905.  
  3906. ; Dispatch prebuilt NetBios session scb, enter with bx pointing to scb.
  3907. ; Returns status in al (and ah too). Allows STARLAN Int 2ah for netint.
  3908. SESSION    PROC    NEAR    
  3909.     push    es            ; save es around call
  3910.     mov    ax,ds
  3911.     mov    es,ax            ; make es:bx point to scb in data seg
  3912.     mov    ax,exnbios        ; funct 4 execute netbios, for Int 2ah
  3913.     int    netint            ; use NetBios interrupt
  3914.     pop    es            ; saved registers
  3915.     ret                ; exit with status in ax
  3916. SESSION    ENDP
  3917.  
  3918. ; Start a TCP/IP Telnet session. Set nettype if successful.
  3919. tcpstart proc    near
  3920.     mov    bx,offset tcpdata    ; pass near pointer to msntni.asm
  3921.     call    dword ptr tcponptr    ; call ktcpstart
  3922.     cmp    ax,2            ; successful?
  3923.     je    tcpstart1        ; e = yes
  3924.     call    tcpclose
  3925.     stc                ; fail
  3926.     ret
  3927. tcpstart1:mov    pcnet,2
  3928.     or    nettype,tcpnet        ; say a session is active
  3929.     clc
  3930.     ret
  3931. tcpstart endp
  3932.  
  3933. ; Close/shutdown/terminate a TCP/IP Telnet session
  3934. tcpclose proc    near
  3935.     call    dword ptr tcpoffptr    ; call ktcpstop
  3936.     and    nettype,not tcpnet    ; clear activity flag
  3937.     mov    portn.portrdy,0        ; say the comms port is not ready
  3938.     mov    pcnet,0            ; say no network
  3939.     call    serrst            ; reset the serial port for reiniting
  3940.     cmp    ax,1            ; successful?
  3941.     je    tcpclo2            ; e = yes
  3942. tcpclo1:stc                ; fail
  3943.     ret
  3944. tcpclo2:
  3945.     clc
  3946.     ret
  3947. tcpclose endp
  3948.  
  3949. ; Make a NetBios virtual circuit Session, given preset scb's from proc chknet.
  3950. ; For Server mode, does a Listen to '*', otherwise does a Call to indicated
  3951. ; remote node. Updates vcid number in scb's. Shows success or fail msg.
  3952. ; Updates network status byte pcnet to 2 if session is established.
  3953. ; Does nothing if a session is active upon entry; otherwise, does a network
  3954. ; hangup first to clear old session material from adapter board. This is
  3955. ; the second procedure to call in initializing the network for usage.
  3956. SETNET    PROC    NEAR            ; NetBios, make a connection
  3957.     cmp    lposted,1        ; Listen pending?
  3958.     je    setne0            ; e = yes, exit now
  3959.     cmp    pcnet,1            ; session active?
  3960.     jbe    setne1            ; be = no
  3961.     clc
  3962. setne0:    ret
  3963.                     ; No Session
  3964. setne1:    call    nethangup        ; clear old session material
  3965.     test    flags.remflg,dserver    ; Server mode?
  3966.     jz    setne2            ; z = no, file xfer or Connect
  3967.                     ; Server mode, post a Listen (async)
  3968.     mov    lsn.scb_rname,'*'    ; accept anyone
  3969.     mov    ax,500
  3970.     call    pcwait            ; 0.5 sec wait
  3971.     mov    lposted,1        ; set listen interlock flag
  3972.     mov    lsn.scb_cmd,nlisten+nowait ; do LISTEN command, no wait
  3973.     push    bx            ; save reg
  3974.     mov    bx,offset lsn
  3975.     call    session
  3976.     pop    bx
  3977.     ret
  3978. setne2:                    ; Non-server (Client) mode
  3979.     test    nettype,starlan        ; STARLAN?
  3980.     jz    setne2a            ; z = no
  3981.     cmp    xmt.scb_vrlen,0        ; yes, using long name support?
  3982.     je    setne2a            ; e = no
  3983.     push    es            ; save reg
  3984.     push    ds
  3985.     pop    es            ; make es:bx point to xmt scb
  3986.     push    bx            ; save reg
  3987.     mov    bx,offset xmt        ; use xmt scb for the call
  3988.     mov    xmt.scb_cmd,ncall    ; CALL_ISN, vrname + vrlen are ready
  3989.     int    5bh            ; STARLAN CALL Int 5bh, wait
  3990.     pop    bx
  3991.     pop    es            ; restore regs
  3992.     jmp    short setne3        ; finish up
  3993.  
  3994.                     ; Regular Netbios Call
  3995. setne2a:cmp    flags.comflg,'O'    ; Opennet network? (FGR)
  3996.     jne    setne2b            ; ne = no
  3997.     mov    xmt.scb_rname+15,'v' ; fix name to use VT port under nameserver
  3998.     mov    rcv.scb_rname+15,'v'
  3999. setne2b:mov    xmt.scb_cmd,ncall    ; CALL, wait for answer
  4000.     push    bx            ; save reg
  4001.      mov    bx,offset xmt        ; setup scb pointer
  4002.     call    session
  4003.     pop    bx            ; restore register
  4004.  
  4005. setne3:                    ; common Call completion, show status
  4006.     test    xmt.scb_err,0ffh    ; is there a non-zero return code?
  4007.     jnz    setne3a            ; nz = yes, do bad return
  4008.     or    al,al            ; check error return
  4009.     jnz    setne3b            ; nz = bad connection
  4010.     jmp    short setne4        ; good connection so far
  4011.  
  4012.                     ; We try twice to allow for R1, and R3
  4013.                     ; versions of the nameservers
  4014. setne3b:cmp    flags.comflg,'O'    ; Opennet netnork? (FGR)
  4015.     jne    setne3a            ; ne = no
  4016.     mov    xmt.scb_rname+15,' '    ; try generic port under nameserver
  4017.     mov    rcv.scb_rname+15,' '
  4018.                     ; Regular Netbios Call
  4019.     mov    xmt.scb_cmd,ncall    ; CALL, wait for answer
  4020.     mov    bx,offset xmt        ; setup scb pointer
  4021.     call    session
  4022.  
  4023.                     ; common Call completion, show status
  4024.     test    xmt.scb_err,0ffh    ; is there a non-zero return code?
  4025.     jnz    setne3a            ; nz = yes, do bad return
  4026.     or    al,al            ; check error return
  4027.     jz    setne4            ; z = good connection so far
  4028. setne3a:mov    dx,offset nbadset    ; say can't reach remote node
  4029.     mov    ah,prstr
  4030.     int    dos
  4031.     call    saynode            ; show remote host node name
  4032.     jmp    short setne4c
  4033.                     ; keep results of Call (vcid)
  4034. setne4:    mov    al,xmt.scb_vcid        ; local session number
  4035.     mov    rcv.scb_vcid,al        ; for receiver too
  4036.     mov    can.scb_vcid,al        ; for sending Breaks
  4037.     mov    pcnet,2            ; say session has started
  4038.  
  4039. ; Here is the real difference between Opennet and generic Netbios.
  4040. ; The Opennet Virtual Terminal Services exchange a small handshake at connect
  4041. ; time. After that it is just normal Netbios data transfer between the host
  4042. ; and Kermit.
  4043.     cmp    flags.comflg,'O'    ; Opennet netnork? (FGR)
  4044.     jne    setne4o            ; ne = no
  4045.     push    si
  4046.     push    di
  4047.     mov    si,offset ivt1str    ; protocol string "iVT1\0"
  4048.     mov    di,offset xmtbufx    ; buffer
  4049.     call    strcpy            ; copy asciiz string
  4050.     mov    xmtcnt,5        ; length of asciiz string, for send
  4051.     pop    di
  4052.     pop    si
  4053.     call    send            ; send signon packet
  4054. ; Note to Opennet purists: this just sends the handshake string to the host
  4055. ; system without checking for an appropriate response. Basically, I am just
  4056. ; very willing to talk to ANY VT server, and do the host response checking
  4057. ; (if desired) in a Kermit script file (so its optional).
  4058. setne4o:
  4059.     test    flags.remflg,dregular+dquiet ; regular or quiet display?
  4060.     jnz    setne4c            ; nz = yes, show only no-connect msg
  4061.     mov    dx,offset ngodset    ; say good connection
  4062.     mov    ah,prstr
  4063.     int    dos
  4064.     call    saynode            ; show remote host name
  4065. setne4c:cmp    pcnet,1            ; check connection again
  4066.     ja    setne5            ; a = good so far
  4067.     stc                ; set carry for failure
  4068.     ret
  4069. setne5:    clc                ; carry clear for success
  4070.     ret
  4071. SETNET    ENDP
  4072.  
  4073. saynode    proc    near        ; display node name on screen, si=name ptr
  4074.     push    ax
  4075.     push    cx
  4076.     push    dx
  4077.     push    si
  4078.     mov    ah,conout
  4079.     mov    si,offset nambuf    ; remote node string
  4080.     mov    cx,64            ; up to 64 bytes long
  4081. saynod1:cld
  4082.     lodsb                ; get remote node name char into al
  4083.     mov    dl,al
  4084.     int    dos            ; display it
  4085.     cmp    al,' '            ; was it a space?
  4086.     jbe    saynod2            ; be = yes, quit here
  4087.     loop    saynod1            ; do all chars
  4088. saynod2:mov    ah,prstr
  4089.     mov    dx,offset crlf
  4090.     int    dos
  4091.     pop    si
  4092.     pop    dx
  4093.     pop    cx
  4094.     pop    ax
  4095.     ret
  4096. saynode    endp
  4097.  
  4098. LPOST    PROC    FAR        ; Interrupt Post routine for Listen call
  4099.     push    ds        ; update vcid and calling node name in scb's
  4100.     push    cx    
  4101.     push    es
  4102.     push    si
  4103.     push    di
  4104.     mov    cx,data        ; reestablish data segment
  4105.     mov    ds,cx
  4106.     mov    es,cx
  4107.     mov    si,offset lsn.scb_rname    ; copy remote name to rcv and xmt scbs
  4108.     push    si
  4109.     mov    di,offset rcv.scb_rname
  4110.     mov    cx,8            ; 16 byte field
  4111.     cld
  4112.     rep    movsw
  4113.     mov    cx,8
  4114.     pop    si
  4115.     push    si
  4116.     mov    di,offset xmt.scb_rname
  4117.     rep    movsw
  4118.     mov    cx,8
  4119.     pop    si
  4120.     mov    di,offset nambuf    ; and to nambuf for display
  4121.     rep    movsw
  4122.     mov    cl,lsn.scb_vcid        ; local session number
  4123.     mov    rcv.scb_vcid,cl
  4124.     mov    xmt.scb_vcid,cl
  4125.     mov    can.scb_vcid,cl
  4126.     mov    lposted,0        ; clear interlock flag
  4127.     mov    pcnet,2            ; say net ready due to a Listen
  4128.     pop    di
  4129.     pop    si
  4130.     pop    es
  4131.     pop    cx
  4132.     pop    ds
  4133.     iret                ; return from interrupt
  4134. LPOST    ENDP
  4135.  
  4136.  
  4137. NETHANGUP PROC    NEAR             ; disconnect network session, keep names
  4138.     mov    al,flags.comflg        ; get type of port
  4139.     cmp    al,'U'            ; Ungermann-Bass port? [ohl]
  4140.     je    nethang2        ; e = yes [ohl]
  4141.     cmp    al,'W'            ; Novell?
  4142.     je    nethang2        ; e = yes
  4143.     cmp    al,'C'            ; 3Com BAPI interface?
  4144.     je    nethang2        ; e = yes
  4145.     cmp    al,'D'            ; DECnet?
  4146.     je    nethang3        ; e = yes
  4147.     cmp    al,'T'            ; Novell TELAPI?
  4148.     je    nethang3        ; e = yes
  4149.     cmp    al,'t'            ; TCP/IP?
  4150.     jne    nethang1c        ; ne = no
  4151.     jmp    nethang6
  4152. nethang1c:cmp    al,'E'            ; EBIOS?
  4153.     jne    nethang1b        ; ne = no
  4154.     jmp    nethang8        ; e = yes
  4155. nethang1b:cmp    al,'I'            ; TES?
  4156.     jne    nethang1a        ; ne = no
  4157.     jmp    teshang
  4158. nethang1a:
  4159.     cmp    pcnet,0            ; network started?
  4160.     jne    nethang1d        ; ne = yes
  4161.     clc
  4162.     ret
  4163. nethang1d:push    bx            ; NetBios network
  4164.     mov    bx,offset can 
  4165.     mov    can.scb_cmd,ncancel    ; set cancel op code
  4166.     mov    can.scb_baddr,offset lsn ; cancel listens
  4167.     mov    lposted,0        ; say no listen
  4168.     call    session
  4169.     mov    can.scb_baddr,offset rcv ; cancel receives
  4170.     call    session
  4171.     mov    rposted,0        ; say no receives posted
  4172.     mov    can.scb_baddr,offset xmt ; cancel sends
  4173.     call    session
  4174.     mov    sposted,0        ; say no sends posted
  4175.     mov    xmtcnt,0        ; reset output buffer counter
  4176.     mov    xmt.scb_cmd,nhangup    ; hangup, and wait for completion
  4177.     mov    bx,offset xmt
  4178.     call    session
  4179.     pop    bx
  4180.     jmp    nethang7
  4181.                     ; UB network [ohl] +++
  4182. nethang2:call    ubclose            ; close connection if any [ohl]
  4183.     mov    xmtcnt,0
  4184.     clc
  4185.     ret                ;  [ohl] ---
  4186. nethang3:test    nettype,declat        ; DECnet LAT active?
  4187.     jz    nethang4        ; z = no
  4188.     mov    dx,lathand        ; LAT handle
  4189.     or    dx,dx            ; invalid handle?
  4190.     jz    nethang3b        ; z = yes
  4191.     mov    ax,latclose
  4192.     int    latint
  4193.     mov    ax,latseg        ; allocated memory segment
  4194.     or    ax,ax            ; was it used?
  4195.     jz    nethang3a        ; z = no
  4196.     mov    dx,lathand
  4197.     mov    ax,latstat        ; get status of session
  4198.     int    latint
  4199.     test    ah,4            ; session not active bit set?
  4200.     jz    nethang3b        ; z = no, keep the buffer
  4201.     push    es
  4202.     mov    ax,latseg
  4203.     mov    es,ax
  4204.     mov    ah,freemem        ; free allocated memory segment @ES
  4205.     int    dos            ; free the block
  4206.     pop    es
  4207.     mov    latseg,0        ; clear remembered segment address
  4208.     mov    word ptr latscbptr+2,0    ; clear this pointer (same as latseg)
  4209. nethang3a:cmp    word ptr latscbptr+2,0    ; any pointer?
  4210.     je    nethang3b        ; e = no
  4211.     cmp    latversion,4        ; version 4?
  4212.     jb    nethang3b        ; b = no
  4213.     push    es
  4214.     les    bx,latscbptr
  4215.     mov    dx,lathand
  4216.     mov    ax,latscbfree        ; free SCB interior to LAT
  4217.     int    latint
  4218.     mov    word ptr latscbptr+2,0
  4219.     pop    es
  4220. nethang3b:
  4221.     and    nettype,not declat    ; remove net type bit
  4222.     mov    lathand,0        ; invalidate the handle
  4223.  
  4224. nethang4:test    nettype,decnet        ; DEC CTERM active?
  4225.     jz    nethang5        ; z = no
  4226.     mov    dx,decneth        ; DECnet CTERM handle
  4227.     or    dx,dx            ; invalid handle?
  4228.     jz    nethang7        ; z = yes
  4229.     mov    ax,dclose        ; CTERM close
  4230.     int    decint
  4231.     mov    decneth,0        ; invalidate the handle
  4232.     mov    ax,decseg        ; allocated memory segment
  4233.     or    ax,ax            ; ever used?
  4234.     jz    nethang5a        ; z = no
  4235.     mov    es,ax
  4236.     mov    ah,freemem        ; free allocated memory segment @ES
  4237.     int    dos            ; free the block
  4238.     mov    decseg,0        ; clear remembered segment address
  4239. nethang5a:and    nettype,not decnet    ; remove net type bit
  4240.     jmp    short nethang7
  4241.  
  4242. nethang5:test    nettype,telapi        ; Novell TELAPI?
  4243.     jz    nethang6        ; e = no
  4244.     mov    xmtcnt,0
  4245.     push    bx
  4246.     mov    bx,telses        ; session number
  4247.     mov    ah,telclose        ; close session
  4248.     call    tes_service
  4249.     pop    bx
  4250.     or    ax,ax            ; status
  4251.     js    nethang7        ; s = error
  4252.     and    nettype,not telapi    ; remove net type bit
  4253.     jmp    short nethang7
  4254. nethang6:test    nettype,tcpnet        ; TCP Telnet?
  4255.     jz    nethang7        ; z = no
  4256.     call    tcpclose        ; close the system
  4257. nethang7:
  4258.     mov    portn.portrdy,0        ; say the comms port is not ready
  4259.     mov    pcnet,1            ; say network but no session
  4260.     call    serrst            ; reset the serial port for reiniting
  4261.     clc
  4262.     ret
  4263. nethang8:mov    dx,ebport        ; EBIOS
  4264.     mov    ax,ebmodem*256+0    ; reset outgoing DTR and RTS leads
  4265.     int    rs232
  4266.     mov    ah,ebredir        ; do redirect away from EBIOS
  4267.     mov    ebcoms+1,0        ; set port to hardware
  4268.     int    rs232
  4269.     jmp    short nethang7
  4270. NETHANGUP ENDP
  4271.  
  4272. ; TES hangup session
  4273. teshang    proc    near
  4274.     mov    temp,0            ; retry counter
  4275. teshan1:call    tesstate        ; get session state to AH
  4276.     test    ah,2            ; is this session active?
  4277.     jz    teshan3            ; z = no, but keep held sessions
  4278.     mov    ah,tesdrop        ; drop a session
  4279.     mov    al,tesses        ; the session
  4280.     call    tes_service
  4281.     or    ah,ah            ; status
  4282.     jz    teshan3            ; z = success
  4283.     stc                ; say failure
  4284.     ret
  4285. teshan3:and    nettype,not tes        ; successful hangup
  4286.     mov    tesses,0        ; clear session
  4287.     mov    portn.portrdy,0        ; say the comms port is not ready
  4288.     mov    pcnet,1            ; say network but no session
  4289.     call    serrst            ; reset the serial port for reiniting
  4290.     clc
  4291.     ret
  4292. teshang    endp
  4293.  
  4294. ; Ungermann Bass. Do a disconnect from the current connection.
  4295. ubclose proc    near
  4296.     push    ax
  4297.     push    cx
  4298.     test    nettype,netone        ; UB network has been activated?
  4299.     jz    ubclos4            ; z = no
  4300.     mov    ax, ncistat        ; get status             [ohl]
  4301.     int    netci
  4302.      or    ch,ch            ; check if we have a connection     [ohl]
  4303.     jz    ubclos2            ; z = no             [ohl]
  4304.     mov    ax, ncicont        ; control function         [ohl]
  4305.     mov    cx, ncidis        ; say disconnect         [ohl]
  4306.     int    netci
  4307. ubclos1:call    ubrecv            ; read response from net cmdintpr[ohl]
  4308.     jnc    ubclos1            ; continue till no chars     [ohl]
  4309.     mov    ax, ncistat        ; get status again
  4310.     int    netci
  4311.     or    ch,ch            ; check if we have a connection
  4312.     jnz    ubclos3            ; nz = yes, had more than one
  4313. ubclos2:and    nettype,not netone    ; remove network type
  4314.     mov    pcnet,1            ; net but no connection
  4315.     mov    portn.portrdy,0        ; say the comms port is not ready
  4316. ubclos3:pop    cx
  4317.     pop    ax
  4318.     ret
  4319. ubclos4:test    nettype,bapi+tcpnet    ; 3Com BAPI or TCP Telnet in use?
  4320.     jz    ubclos3            ; z = no
  4321.     mov    ah,bapieecm        ; control Enter Command Mode char
  4322.     mov    al,1            ; enable it
  4323.     int    bapiint
  4324.     test    nettype,tcpnet        ; TCP Telnet?
  4325.     jz    ubclos3            ; z = no
  4326.     call    tcpclose        ; close this way too
  4327.     jmp    short ubclos3
  4328. ubclose endp
  4329.  
  4330. ; Ungermann Bass/Novell. Put current connection on Hold. Requires keyboard
  4331. ; verb \knethold to activate. Should return to Connect mode to see NASI. [jrd]
  4332. ubhold    proc    near
  4333.     push    ax
  4334.     push    cx
  4335.     test    nettype,netone        ; UB/Novell network active?
  4336.     jz    ubhold1            ; z = no
  4337.     mov    ax,ncistat        ; get link status
  4338.     int    netci
  4339.     or    ch,ch            ; connection active?
  4340.     jz    ubhold1            ; z = no
  4341.     mov    ax,ncicont        ; control command
  4342.     mov    cl,ncihld        ; place circuit on HOLD
  4343.     int    netci
  4344.     jmp    short ubhold3
  4345. ubhold1:test    nettype,bapi+tcpnet    ; 3Com BAPI or TCP Telnet?
  4346.     jz    ubhold2            ; z = no
  4347.     mov    ah,bapiecm        ; do Enter Command Mode char
  4348.     int    bapiint
  4349.     jmp    short ubhold3
  4350. ubhold2:test    nettype,tes        ; TES?
  4351.     jz    ubhold3            ; z = no
  4352.     mov    ah,testalk        ; TES get command interpreter
  4353.     mov    dx,tesport        ; "serial port"
  4354.     int    rs232
  4355. ubhold3:pop    cx
  4356.     pop    dx
  4357.     clc
  4358.     ret
  4359. ubhold    endp
  4360.  
  4361. ; Called when Kermit exits. Name passed to mssker by initialization lclini
  4362. ; in word lclexit.
  4363. NETCLOSE PROC    NEAR            ; close entire network connection
  4364.     call    nethangup        ; close connections
  4365. netclo1:cmp    lnamestat,2        ; local Netbios name present?
  4366.     jb    netclo2            ; b = no
  4367.     push    bx
  4368.     mov    bx,offset xmt
  4369.     mov    xmt.scb_cmd,ndelete    ; delete our local Kermit name
  4370.     call    session            ;  from net adapter board
  4371.     pop    bx
  4372.     mov    pcnet,0            ; say no network
  4373.     mov    lnamestat,1        ; local name present, inactive
  4374.     mov    portn.portrdy,0        ; say comms port is not ready
  4375.     and    nettype,not netbios    ; remove network kind
  4376. netclo2:clc
  4377.     ret
  4378. NETCLOSE ENDP    
  4379.  
  4380. ; Start connection process to network. Obtains Network board local name
  4381. ; and appends '.K' to form Kermit's local name (removed when Kermit exits).
  4382. ; If no local name is present then use name 'mskermit.K'.
  4383. ; Sets local name in scb's for xmt, rcv, lsn. (Does not need DOS 3.x)
  4384. ; Sets NETDONE pointer to procedure netclose for Kermit exit.
  4385. ; Verifies existance of interrupt 5ch support, verifies vendor specific
  4386. ; support for BREAK and other features, sets network type bit in nettype,
  4387. ; sets BREAK support in nsbrk, hangsup old session if new node name given,
  4388. ; fills in local and remote node names and name number in scbs (including ISN
  4389. ; names for STARLAN), and sets network status byte pcnet to 0 (no net) or
  4390. ; to 1 (net ready). This is the first procedure called to init network usage.
  4391. ; Byte count of new host name is in temp from COMS.
  4392. chknet    proc    near
  4393.     cmp    flags.comflg,'U'    ; Ungermann Bass network?
  4394.     jb    chknea            ; b = no, (ae includes U and W)
  4395.     mov    pcnet,0            ; force reactivation of UB net
  4396. chknea:    cmp    pcnet,2            ; session active now?
  4397.     jb    chknec            ; b = no
  4398.     cmp    newnambuf,0        ; non-zero if new destination name
  4399.     je    chkneb            ; e = none, resume old session
  4400.     call    chknew            ; Resume current session?
  4401.     jnc    chkneb            ; nc = no
  4402. chknex:    ret                ; resume old one
  4403. chkneb:    jmp    chknet1            ; skip presence tests
  4404.  
  4405. chknec:                ; setup addresses and clear junk in scb's
  4406.     cmp    pcnet,0            ; have we been here already?
  4407.     je    chkned            ; e = no
  4408.     jmp    chknet1            ; yes, skip init part
  4409. chkned:    mov    xmtcnt,0        ; say buffer is empty
  4410.     mov    nsbrk,0            ; assume no BREAK across network
  4411.     and    nettype,not netbios    ; say no NetBios network yet
  4412.     call    chknetbios        ; is Netbios present?
  4413.     jc    chknet0            ; c = not present
  4414.     or    nettype,netbios        ; say have NetBios network
  4415.     call    chkstarlan        ; is AT&T StarLAN present?
  4416.     jc    chknet1            ; c = no
  4417.     or    nettype,starlan        ; say using STARLAN, have int 2ah
  4418.     mov    nsbrk,1            ; network BREAK supported
  4419.     jmp    short chknet1
  4420.  
  4421. chknet0:mov    pcnet,0            ; no network yet
  4422.     push    dx
  4423.     mov    ah,prstr
  4424.     mov    dx,offset nonetmsg    ; say network is not available
  4425.     int    dos
  4426.     pop    dx
  4427.     stc                ; set carry for failure
  4428.     ret                ; and exit now
  4429.  
  4430.                     ; net ready to operate
  4431. chknet1:mov    portn.portrdy,1        ; say the comms port is ready
  4432.     cmp    newnambuf,0        ; non-zero if new destination name
  4433.     jne    chkne1e            ; ne = new name given
  4434.     jmp    chknet2            ; nothing, so leave names intact
  4435. chkne1e:cmp    pcnet,2            ; is session active now?
  4436.     jb    chkne1d            ; b = no
  4437.     call    nethangup        ; hangup net to clear old connection
  4438.  
  4439. chkne1d:push    si            ; start fresh connection
  4440.     push    di
  4441.     push    es
  4442.     push    ds
  4443.     pop    es            ; make es:di point to data segment
  4444.     cld
  4445.     mov    cx,8            ; 16 bytes for a node name
  4446.     mov    ax,'  '            ; first, fill with spaces
  4447.     mov    di,offset xmt.scb_rname ; remote name field, clear it
  4448.     rep    stosw
  4449.     test    nettype,starlan        ; STARLAN?
  4450.     jz    chkne1b            ; z = no
  4451.                     ; begin STARLAN section    
  4452.     mov    xmt.scb_vrname,0    ; STARLAN var length name ptr
  4453.     mov    xmt.scb_vrname+2,0    ; segement of name    
  4454.     mov    xmt.scb_vrlen,0        ; and its length
  4455.     mov    di,offset nambuf    ; source of text
  4456.     mov    dx,di
  4457.     call    strlen            ; length of new name to cx
  4458.     cmp    cx,16            ; > 16 chars in remote node name?
  4459.     ja    chkne1a            ; a = yes, too long for Netbios
  4460.     mov    al,'/'            ; scan for slashes in name
  4461.     cld
  4462.     repne    scasb            ; look for the slash
  4463.     jne    chkne1b        ; ne = none, do regular Netbios name storage
  4464. chkne1a:                ; STARLAN ISN long remote name support
  4465.     mov    dx,offset nambuf    ; STARLAN var length name ptr
  4466.     mov    xmt.scb_vrname,dx    
  4467.     mov    xmt.scb_vrname+2,data    ; segment of remote name
  4468.     call    strlen            ; get name length again (in cx)
  4469.     mov    xmt.scb_vrlen,cl    ; indicate its length
  4470.     jmp    short chkne1c        ; copy blanks in remote name field
  4471.                     ; end STARLAN section
  4472.  
  4473. chkne1b:                ; Regular Netbios form
  4474.     mov    si,offset nambuf    ; source of text
  4475.     mov    dx,si
  4476.     call    strlen            ; length to cx
  4477.     cmp    cx,16
  4478.     jbe    chkne1f            ; be = in bounds
  4479.     mov    cx,16            ; chop to 16 (prespace filled above)
  4480. chkne1f:mov    di,offset xmt.scb_rname ; destination is remote name
  4481.     rep    movsb            ; copy text to transmitter's scb
  4482. chkne1c:mov    cx,8            ; 8 words
  4483.     mov    si,offset xmt.scb_rname ; from here
  4484.     mov    di,offset rcv.scb_rname ; to receiver's scb also
  4485.     rep    movsw
  4486.     pop    es
  4487.     pop    di
  4488.     pop    si
  4489.     mov    newnambuf,0        ; say new name is established now
  4490.  
  4491. chknet2:cmp    pcnet,0            ; started net?
  4492.     je    chknet2c        ; e = no
  4493.     clc
  4494.     ret                ; else quit here
  4495. chknet2c:call    setnbname        ; establish local Netbios name
  4496.     jnc    chknet9            ; nc = success
  4497.     ret
  4498. chknet9:mov    pcnet,1            ; network is present (but not active)
  4499.     mov    al,xmt.scb_num        ; name number
  4500.     mov    rcv.scb_num,al
  4501.     mov    lsn.scb_num,al
  4502.     push    es
  4503.     push    si
  4504.     push    di
  4505.     mov    si,ds
  4506.     mov    es,si
  4507.     mov    si,offset xmt.scb_lname
  4508.     mov    di,offset rcv.scb_lname ; put in receiver scb too
  4509.     mov    cx,8
  4510.     rep    movsw
  4511.     mov    cx,8
  4512.     mov    si,offset xmt.scb_lname
  4513.     mov    di,offset lsn.scb_lname    ; in Listen scb also
  4514.     rep    movsw
  4515.     pop    si
  4516.     pop    di
  4517.     pop    es
  4518.     clc
  4519.     ret
  4520. chknet    endp
  4521.  
  4522. ; Service SET NETBIOS-NAME name   command at Kermit prompt level
  4523. setnbios    proc    near
  4524.     mov    dx,offset decbuf    ; work buffer
  4525.     mov    bx,offset setnbhlp    ; help
  4526.     mov    ah,cmword        ; get netbios name
  4527.     call    comnd
  4528.     jc    setnb3            ; c = failure
  4529.     push    ax            ; save char count
  4530.     mov    ah,cmeol        ; get a confirmation
  4531.     call    comnd
  4532.     pop    ax
  4533.     jc    setnb3            ; c = failure
  4534.     cmp    lnamestat,2        ; is name fixed already?
  4535.     je    setnb2            ; e = yes
  4536.     mov    cx,ax            ; char count
  4537.     jcxz    setnb3            ; z = enter no new name
  4538.     cmp    cx,16            ; too long?
  4539.     jbe    setnb1            ; be = no
  4540.     mov    cx,16            ; truncate to 16 chars
  4541. setnb1:    mov    si,offset decbuf    ; work buffer
  4542.     mov    di,offset deflname    ; default name
  4543.     push    es
  4544.     mov    ax,ds
  4545.     mov    es,ax
  4546.     cld
  4547.     rep    movsb            ; copy the name
  4548.     mov    al,' '            ; pad with spaces
  4549.     mov    cx,offset deflname+16    ; stopping place+1
  4550.     sub    cx,di            ; number of spaces to write
  4551.     rep    stosb            ; won't do anything if cx == 0
  4552.     pop    es
  4553.     mov    lnamestat,1        ; say have new local name
  4554.     call    setnbname        ; do the real NetBios resolution
  4555.     ret                ; returns carry set or clear
  4556. setnb2:    mov    ah,prstr
  4557.     mov    dx,offset setnbad    ; say name is fixed already
  4558.     int    dos
  4559. setnb3:    stc                ; failure
  4560.     ret
  4561. setnbios endp
  4562.  
  4563. chknetbios proc    near            ; Test for Netbios presence, IBM way
  4564.     push    es
  4565.     mov    ah,35h            ; DOS get interrupt vector
  4566.     mov    al,netint        ; the netbios vector
  4567.     int    dos            ; returns vector in es:bx
  4568.     mov    ax,es
  4569.     or    ax,ax            ; undefined interrupt?
  4570.     jz    chknb1            ; z = yes
  4571.     cmp    byte ptr es:[bx],0cfh    ; points at IRET?
  4572.     je    chknb1            ; e = yes
  4573.     mov    xmt.scb_cmd,7fh ; presence test, 7fh is illegal command code
  4574.     mov    xmt.scb_err,0        ; clear response field
  4575.     push    bx
  4576.     mov    bx,offset xmt        ; address of the session control block
  4577.     call    session            ; execute operation
  4578.     pop    bx
  4579.     mov    al,xmt.scb_err        ; get response
  4580.     cmp    al,3            ; 'illegal function', so adapter is ready
  4581.     je    chknb1            ; e = success
  4582.     or    al,al
  4583.     jnz    chknb2            ; nz = not "good response" either
  4584. chknb1:    pop    es
  4585.     clc                ; netbios is present
  4586.     ret
  4587. chknb2:    pop    es
  4588.     stc                ; netbios is not present
  4589.     ret
  4590. chknetbios endp
  4591.  
  4592. chkstarlan proc near            ; AT&T STARLAN board check
  4593.     push    es
  4594.     mov    ah,35h            ; DOS get interrupt vector
  4595.     mov    al,2ah            ; PC net vector 2ah
  4596.     int    dos            ; returns vector in es:bx
  4597.     mov    ax,es
  4598.     or    ax,ax            ; undefined interrupt?
  4599.     jz    chkstar1        ; z = yes
  4600.     cmp    byte ptr es:[bx],0cfh    ; points at IRET?
  4601.     je    chkstar1        ; e = yes
  4602.     xor    ah,ah            ; vendor installation check on int 2ah
  4603.     xor    al,al            ; do error retry
  4604.     int    2ah            ; session level interrupt
  4605.     cmp    ah,0ddh            ; 0ddh = magic number, success?
  4606.     jne    chkstar1        ; ne = no
  4607.                     ; Test for vector
  4608.     mov    ah,35h            ; DOS get interrupt vector
  4609.     mov    al,5bh            ; 5bh = STARLAN netbios ext'd vector
  4610.     int    dos            ; returns vector in es:bx
  4611.     mov    ax,es
  4612.     or    ax,ax            ; undefined interrupt?
  4613.     jz    chkstar1        ; z = yes
  4614.     cmp    byte ptr es:[bx],0cfh    ; points to IRET?
  4615.     je    chkstar1        ; e = yes
  4616.     pop    es
  4617.     clc                ; StarLAN is present
  4618.     ret
  4619. chkstar1:pop    es
  4620.     stc                ; StarLAN is not present
  4621.     ret
  4622. chkstarlan endp
  4623.  
  4624. ; Put a local name into the Netbios name table, ask user if conflicts.
  4625. setnbname proc    near
  4626.     cmp    lnamestat,2        ; validiated local Netbios name?
  4627.     jb    setnbn1            ; b = no
  4628.     ret                ; else quit here
  4629. setnbn1:call    chknetbios        ; Netbios presence check
  4630.     jnc    setnbn1a        ; nc = present
  4631.     ret
  4632.  
  4633. setnbn1a:mov    ah,prstr
  4634.     mov    dx,offset netmsg1    ; say checking node name
  4635.     int    dos
  4636.     push    word ptr xmt.scb_rname    ; save first two bytes (user spec)
  4637.     mov    byte ptr xmt.scb_rname,'*' ; call to local name
  4638.     push    bx
  4639.     mov    xmt.scb_cmd,naustat    ; get Network Adapter Unit status
  4640.     mov    bx,offset xmt
  4641.     call    session
  4642.     pop    bx
  4643.     pop    word ptr xmt.scb_rname    ; restore remote name first two bytes
  4644. setnbn2:push    es
  4645.     push    si
  4646.     push    di
  4647.     mov    si,ds
  4648.     mov    es,si
  4649.     cld
  4650.     cmp    lnamestat,0        ; local name specified?
  4651.     jne    setnbn3            ; ne = yes
  4652.     mov    si,offset xmtbuf+60 ; where local name is returned (1st entry)
  4653.     cmp    word ptr xmtbuf+58,0    ; is local name empty?
  4654.     jne    setnbn4            ; ne = no, use name from table
  4655. setnbn3:mov    si,offset deflname    ; else use default local name
  4656. setnbn4:mov    di,offset xmt.scb_lname ; where to put it in scb
  4657.     mov    cx,14            ; 16 bytes minus extension of '.K'
  4658.     cld                ; append extension of '.K' to loc name
  4659. setnbn5:cmp    byte ptr[si],' ' ; find first space (end of regular node name)
  4660.     jbe    setnbn6            ; be = found one (or control code)
  4661.     movsb                ; copy local name to scb
  4662.     loop    setnbn5            ; continue though local name
  4663. setnbn6:cmp    word ptr [di-2],'K.'    ; is extension '.K' present already?
  4664.     je    setnbn7            ; e = yes, nothing to add
  4665.     cmp    word ptr [di-2],'k.'    ; check lower case too
  4666.     je    setnbn7            ; e = yes, nothing to add
  4667.     mov    word ptr [di],'K.'    ; append our extension of '.K'
  4668.     add    di,2            ; step over our new extension
  4669.     sub    cx,2
  4670.                     ; complete field with spaces
  4671. setnbn7:add    cx,2            ; 15th and 16th chars
  4672.     mov    al,' '            ; space as padding
  4673.     rep    stosb
  4674.     pop    di            ; clean stack from work above
  4675.     pop    si
  4676.     pop    es
  4677.  
  4678.     push    bx            ; Put our new local name in NAU
  4679.     mov    xmt.scb_cmd,nadd    ; ADD NAME, wait
  4680.     mov    bx,offset xmt
  4681.     call    session
  4682.     pop    bx
  4683.     mov    al,xmt.scb_err        ; get error code
  4684.     or    al,al            ; success?
  4685.     jnz    setnbn8            ; nz = no
  4686.     jmp    setnbn12        ; success
  4687. setnbn8:cmp    al,0dh            ; duplicate name in local table?
  4688.     je    setnbn9            ; e = yes
  4689.     cmp    al,16h            ; name used elsewhere?
  4690.     je    setnbn9            ; e = yes
  4691.     cmp    al,19h            ; name conflict?
  4692.     je    setnbn9            ; e = yes
  4693.     push    ax
  4694.     mov    ah,prstr        ; another kind of error
  4695.     mov    dx,offset chkmsg1    ; say can't construct local name
  4696.     int    dos
  4697.     pop    ax
  4698.     call    decout            ; display it (in al)
  4699.     mov    ah,prstr
  4700.     mov    dx,offset crlf
  4701.     int    dos
  4702.     stc                ; set carry for failure
  4703.     ret
  4704.  
  4705. setnbn9:mov    ah,prstr        ; ask for another name
  4706.     mov    dx,offset chkmsg2    ; prompt message
  4707.     int    dos
  4708.     mov    ah,conout        ; show name itself
  4709.     push    si
  4710.     push    cx
  4711.     mov    cx,16            ; 16 bytes in name field
  4712.     mov    si,offset xmt.scb_lname
  4713. setnbn10:lodsb                ; get name char into al
  4714.     mov    dl,al
  4715.     int    dos
  4716.     mov    byte ptr[si-1],' '    ; clear old name as we go
  4717.     loop    setnbn10
  4718.     pop    cx
  4719.     pop    si
  4720.     mov    ah,prstr
  4721.     mov    dx,offset chkmsg3    ; rest of prompt
  4722.     int    dos
  4723.  
  4724.     mov    ah,0ah            ; read buffered line from stdin
  4725.     mov    dx,offset xmtbuf+58    ; where to put text (xmtbuf+60=text)
  4726.     mov    xmtbuf+58,15        ; buf capacity, including cr at end
  4727.     mov    xmtbuf+59,0        ; say text in buffer = none
  4728.     int    dos
  4729.     jc    setnbn11        ; c = error
  4730.     cmp    xmtbuf+59,0        ; any bytes read?
  4731.     je    setnbn11        ; e = no, exit failure
  4732.     mov    ah,prstr        ; say rechecking name
  4733.     mov    dx,offset netmsg1
  4734.     int    dos
  4735.     push    es
  4736.     mov    si,ds
  4737.     mov    es,si
  4738.     mov    si,offset xmtbuf+60    ; where text went
  4739.     mov    di,offset deflname    ; where local name is stored
  4740.     mov    cx,8
  4741.     cld
  4742.     rep    movsw            ; copy 14 chars to deflname
  4743.     mov    byte ptr [di],0        ; null terminator, to be safe
  4744.     pop    es
  4745.     mov    lnamestat,1        ; say local name specified
  4746.     jmp    setnbn2            ; go reinterpret name
  4747.  
  4748. setnbn11:stc                ; set carry for failure
  4749.     ret
  4750.  
  4751. setnbn12:mov    dx,offset netmsg2     ; say net is going
  4752.     mov    ah,prstr
  4753.     int    dos
  4754.     push    si
  4755.     push    di
  4756.     push    es
  4757.     mov    si,ds
  4758.     mov    es,si
  4759.     mov    si,offset xmt.scb_lname ; display our local name
  4760.     mov    di,offset deflname    ; local Netbios name
  4761.     mov    ah,conout
  4762.     mov    cx,16
  4763.     cld
  4764. setnbn13:lodsb                ; byte from si to al
  4765.     stosb                ; and store in local Netbios name
  4766.     mov    dl,al
  4767.     int    dos            ; display it
  4768.     loop    setnbn13
  4769.     pop    es
  4770.     pop    di
  4771.     pop    si
  4772.     mov    lnamestat,2        ; say local name is fixed now
  4773.     mov    ah,prstr
  4774.     mov    dx,offset crlf        ; add cr/lf
  4775.     int    dos
  4776.     clc                ; carry clear for success
  4777.     ret
  4778. setnbname endp
  4779.  
  4780. ; Network session exists. Tell user and ask for new node or Resume.
  4781. ; Returns carry set if Resume response, else carry clear for New.
  4782. chknew    proc    near
  4783.     mov    dx,offset naskpmt    ; prompt for New or Resume
  4784.     call    prompt
  4785.     mov    dx,offset nettab    ; table of answers
  4786.     xor    bx,bx            ; help for the question
  4787.     mov    ah,cmkey        ; get answer keyword
  4788.     mov    comand.cmcr,1        ; allow bare CR's
  4789.     call    comnd
  4790.     mov    comand.cmcr,0        ; dis-allow bare CR's
  4791.     jc    chknew1            ; c = failure, means Resume
  4792.     push    bx
  4793.     mov    ah,cmeol        ; get a confirm
  4794.     call    comnd
  4795.     pop    bx
  4796.     jc    chknew1            ; c = failure, resume session
  4797.     or    bx,bx            ; 0 for new?
  4798.     je    chknew1            ; e = yes, return carry clear
  4799.     stc                ; set carry for resume
  4800. chknew1:ret                ; carry may be set
  4801. chknew    endp
  4802.  
  4803. ;                    ; [ohl] ++++
  4804. ; Verifies existance of interrupt 6Bh support, verifies vendor specific
  4805. ; support for BREAK and other features, sets network type bit in nettype,
  4806. ; sets BREAK support in nsbrk and sets network status byte pcnet to 0
  4807. ; (no net) or to 1 (net ready). This is the first procedure called to
  4808. ; init Ungermann-Bass NETCI terminal port network usage.
  4809. chkub  proc    near
  4810.     push    bx
  4811.         push    es                      ; Test for vector
  4812.         mov     ah,35h                  ; DOS get interrupt vector
  4813.         mov     al,6bh                  ; 6bh = Net/One command interpreter
  4814.                     ;  interface, with break support
  4815.         int     dos                     ; returns vector in es:bx
  4816.     mov    ax,es            ; is vector in rom bios?
  4817.     or    ax,ax            ; undefined vector?
  4818.     jz    chkub0            ; z = yes
  4819.     cmp    byte ptr es:[bx],0cfh    ; points at IRET?
  4820.     je    chkub0            ; e = yes
  4821. ;some    mov    al,0ffh            ; test value (anything non-zero)
  4822. ;emulators mov    ah,2            ; function code for testing net board
  4823. ;flunk    int    netci
  4824. ;this    or    al,al            ; al = 0 means board is ok
  4825. ;test    jnz    chkub0            ; nz = not ok
  4826.     pop    es
  4827.     pop    bx
  4828.         mov     nsbrk,1                 ; network BREAK supported
  4829.         or      nettype,netone        ; say have Net/One
  4830.     clc                ; return success
  4831.     ret
  4832.  
  4833. chkub0:    pop    es            ; clean stack from above
  4834.     pop    bx
  4835.     push    ax
  4836.         push    dx
  4837.         mov     ah,prstr
  4838.         mov     dx,offset nonetmsg      ; say network is not available
  4839.         int     dos
  4840.         pop     dx
  4841.         pop     ax
  4842.         stc                             ; set carry for failure
  4843.         ret                             ; and exit now
  4844. chkub  endp                ; [ohl] ----
  4845.  
  4846. ; local routine to see if we have to transmit an xon
  4847. chkxon    proc    near
  4848.     cmp    flowcnt,0        ; doing flow control?
  4849.     je    chkxo1            ; no, skip all this
  4850.     test    xofsnt,usron        ; did user send an xoff?
  4851.     jnz    chkxo1            ; nz = yes, don't contradict it here
  4852.     test    xofsnt,bufon        ; have we sent a buffer level xoff?
  4853.     jz    chkxo1            ; z = no, forget it
  4854.     cmp    count,mntrgl        ; below (low water mark) trigger?
  4855.     jae    chkxo1            ; no, forget it
  4856.     test    flowcnt,2        ; using RTS/CTS kind?
  4857.     jz    chkxo2            ; z = no
  4858.     cmp    flags.comflg,4        ; using uart?
  4859.     ja    chkxo1            ; a = no, ignore situation
  4860.     push    ax
  4861.     push    dx
  4862.     mov    dx,modem.mddat        ; serial port base address
  4863.     add    dx,4            ; increment to control register
  4864.     in    al,dx
  4865.     or    al,2            ; assert RTS for flow-on
  4866.     jmp    $+2
  4867.     out    dx,al
  4868.     and    xofsnt,off        ; remember we've sent the "xon"
  4869.     pop    dx
  4870.     pop    ax
  4871.                     ; do software flow control too
  4872. chkxo2:    test    flowcnt,1        ; using XON/XOFF kind?
  4873.     jz    chkxo1            ; z = no
  4874.     mov    ah,flowon        ; ah gets xon
  4875.     and    xofsnt,off        ; remember we've sent the xon
  4876.     call    outch2            ; send via non-flow controlled entry point
  4877. chkxo1:    ret
  4878. chkxon    endp
  4879.  
  4880. ; IHOSTS - Initialize the host by sending XOFF, or equivalent.
  4881. ; Requires that the port be initialized before hand.
  4882. ; Do not send flow control if doing half duplex.
  4883.  
  4884. IHOSTS    PROC    NEAR
  4885.     push    ax        ; save the registers
  4886.     push    bx
  4887.     push    cx
  4888.     push    dx
  4889.     mov    xofrcv,off    ; clear old xoff received flag
  4890.     mov    xofsnt,off    ; and old xoff sent flag
  4891.     cmp    portin,0    ; is a comms port active?
  4892.     jle    ihosts1        ; le = no
  4893.     mov    bx,portval
  4894.     mov    ah,byte ptr [bx].flowc ; put wait flow control char in ah
  4895.     or    ah,ah        ; check for null char
  4896.     jz    ihosts1        ; z = null, don't send it
  4897.     cmp    dupflg,0    ; full duplex?
  4898.     jne    ihosts1        ; ne = no, half
  4899.     call    outchr        ; send it
  4900. ihosts1:call    clrbuf        ; clear out interrupt buffer
  4901.     pop    dx            ; empty buffer. we are done here
  4902.     pop    cx
  4903.     pop    bx
  4904.     pop    ax
  4905.     ret
  4906. IHOSTS    ENDP
  4907.  
  4908. ; IHOSTR - initialize the remote host for our reception of a file by
  4909. ; sending the flow-on character (XON typically) to release any held
  4910. ; data. Do not send flow control if doing half duplex.
  4911. IHOSTR    PROC    NEAR
  4912.     push    ax        ; save regs
  4913.     push    bx
  4914.     push    cx
  4915.     mov    xofrcv,off    ; clear old xoff received flag
  4916.     mov    xofsnt,off    ; and old xoff sent flag
  4917.     cmp    portin,0    ; is a comms port active?
  4918.     jle    ihostr1        ; le = no
  4919.     mov    bx,portval
  4920.     mov    ah,byte ptr [bx].flowc+1; put Go-ahead flow control char in ah
  4921.     or    ah,ah        ; check for null char
  4922.     jz    ihostr1        ; z = null, don't send it
  4923.     cmp    dupflg,0    ; full duplex?
  4924.     jne    ihostr1        ; ne = no, half
  4925.     call    outchr        ; send it (release Host's output queue)
  4926. ihostr1:pop    cx
  4927.     pop    bx
  4928.     pop    ax
  4929.     ret
  4930. IHOSTR    ENDP
  4931.  
  4932. ; Send a break out the current serial port.  Returns normally.
  4933. ; Do both regular and long Break. 6 March 1987 [jrd]
  4934.  
  4935. SENDBR    PROC    NEAR
  4936.     push    cx        ; Regular Break entry point
  4937.     mov    cx,275        ; 275 milliseconds in regular Break
  4938.     call    sendbw        ; call worker routine to do it
  4939.     pop    cx
  4940.     clc            ; don't exit Connect mode
  4941.     ret
  4942. SENDBL:    push    cx        ; Long Break entry point
  4943.     mov    cx,1800        ; 1.8 second long break
  4944.     call    sendbw        ; call worker routine to do it
  4945.     pop    cx
  4946.     clc            ; don't exit Connect mode
  4947.     ret
  4948.                 ; worker - send Break for cx millisec
  4949. sendbw:    mov    al,flags.comflg    ; get type of port
  4950.     cmp    al,4        ; running on a UART or network?
  4951.     ja    sendbw2        ; a = yes
  4952.     push    dx        ; UART BREAK
  4953.     mov    dx,modem.mdcom    ; port address
  4954.     in    al,dx        ; get current setting
  4955.     push    ax        ; save setting on the stack
  4956.     or    al,brkbit    ; set send-break bit(s)
  4957.     out    dx,al        ; start the break
  4958.     mov    ax,cx        ; # of ms to wait
  4959.     call    pcwait        ; hold break for desired interval
  4960.     pop    ax        ; restore Line Control Register
  4961.     out    dx,al        ; stop the break
  4962.     pop    ax
  4963.     ret
  4964. sendbw2:cmp    al,'N'        ; is this a NetBios network port?
  4965.     jne    sendbw5        ; ne = no
  4966.     cmp    nsbrk,0        ; is network able to send a break?
  4967.     je    sendbw4        ; e = no
  4968.     test    nettype,starlan    ; STARLAN: network break supported?
  4969.     jz    sendbw4        ; z = no
  4970.     push    bx
  4971.     push    es        ; save es around call
  4972.     push    ds
  4973.     pop    es        ; make es:bx point to scb in data segment
  4974.     mov    bx,offset can    ; use Cancel control block
  4975.     mov    can.scb_cmd,netbrk ; send net Break command
  4976.     int    5bh        ; use network Break interrupt
  4977.     pop    es        ; saved registers
  4978.     pop    bx
  4979. sendbw4:ret
  4980. sendbw5:test    nettype,ebios        ; EBIOS?
  4981.     jz    sendbw6            ; z = no
  4982.     push    ax
  4983.     push    dx
  4984.     mov    dx,ebport        ; port 0..3
  4985.     mov    ah,ebbreak        ; EBIOS send BREAK
  4986.     int    rs232            ; bios send
  4987.     pop    dx
  4988.     pop    ax
  4989.     ret
  4990. sendbw6:test    nettype,netone        ; UB NETCI or Novell NASI/NACS?
  4991.     jz    sendbw7            ; z = no             [ohl]
  4992.     push    cx            ; UB port send break         [ohl]
  4993.     mov    ax,ncicont+0    ; call control, use 0 for network port num
  4994.     mov    cl,ncibrk    ; request break                 [ohl]
  4995.     int    netci        ; Net/One command interface int. (6Bh)     [ohl]
  4996.     pop    cx
  4997.     ret                ;  [ohl] ---
  4998. sendbw7:test    nettype,declat        ; DECnet?
  4999.     jz    sendbw9            ; z = no, CTERM cannot send a BREAK
  5000.     mov    ax,latbreak        ; LAT BREAK command
  5001.     push    dx
  5002.     mov    dx,lathand        ; LAT handle
  5003.     int    latint
  5004.     pop    dx
  5005.     ret
  5006. sendbw9:test    nettype,bapi+tcpnet    ; 3Com BAPI or TCP Telnet?
  5007.     jz    sendbw10        ; z = no
  5008.     mov    ah,bapibrk        ; BAPI, send BREAK
  5009.     xor    dh,dh            ; session id of 0 (external sessions)
  5010.     int    bapiint
  5011.     ret
  5012. sendbw10:test    nettype,telapi        ; Novell TELAPI?
  5013.     jz    sendbw11        ; z = no
  5014.     mov    ah,255            ; Telnet Interpret As Command char
  5015.     call    outchr            ; send it
  5016.     mov    ah,244            ; Telnet Interrupt Process char
  5017.     call    outchr            ; send it
  5018.     ret
  5019. sendbw11:test    nettype,tes        ; TES?
  5020.     jz    sendbw12        ; z = no
  5021.     mov    ah,testalk        ; get command interpreter
  5022.     mov    dx,tesport
  5023.     int    rs232
  5024. sendbw12:ret
  5025. SENDBR    ENDP
  5026.  
  5027. ; Initialization for using serial port.  This routine performs
  5028. ; any initialization necessary for using the serial port, including
  5029. ; setting up interrupt routines, setting buffer pointers, etc.
  5030. ; Doing this twice in a row should be harmless (this version checks
  5031. ; a flag and returns if initialization has already been done).
  5032. ; SERRST below should restore any interrupt vectors that this changes.
  5033. ;
  5034. ; Revised slightly by Joe R. Doupnik 22 Dec 1985 to prevent interrupts
  5035. ; being enabled until we're done, to stop interrupts from occurring when
  5036. ; TX holding buffer becomes empty (a useless interrupt for us), and to
  5037. ; shorten the time between enabling interrupts and our exit.
  5038. ; Returns carry clear if success, else carry set.
  5039. ; 9 July 1989 Add support for 16550/A 14 char receiver fifo.
  5040. SERINI    PROC    NEAR
  5041.     call    pcwtst            ; recalibrate pcwait loop timer
  5042.     cmp    portin,0        ; did we initialize port already?
  5043.     je    serin5            ; e = yes
  5044.     jl    serin0            ; l = no, not yet
  5045.     jmp    serin4            ; yes, update flow and leave
  5046. serin0:    mov    bl,flags.comflg        ; pass current port ident
  5047.     mov    portin,0        ; say have been here once
  5048.     call    comstrt            ; do SET PORT now
  5049.     jnc    serin5            ; nc = success
  5050.     ret                ; failed, exit now
  5051. serin5:    push    bx
  5052.     mov    bx,portval
  5053.     mov    bl,[bx].duplex        ; get full/half duplex flag, local cpy
  5054.     mov    dupflg,bl
  5055.     pop    bx
  5056.     cmp    flags.comflg,4        ; UART?
  5057.     jbe    serin2            ; be = yes, real thing
  5058.     jmp    serin3            ; else try other port kinds
  5059.  
  5060. serin2:    push    bx
  5061.     push    es
  5062.     mov    dx,modem.mdmintc    ; interrupt controller
  5063.     inc    dx            ; look at interrupt mask
  5064.     in    al,dx            ; get interrupt mask
  5065.     mov    savirq,al        ; save state here for restoration
  5066.     or    al,modem.mddis        ; inhibit our IRQ
  5067.     out    dx,al
  5068.     mov    al,byte ptr modem.mdintv ; desired interrupt vector
  5069.     mov    ah,35H            ; Int 21H, function 35H = Get Vector
  5070.     int    dos            ; get vector into es:bx
  5071.     mov    word ptr savsci,bx    ; save address offset of original vector
  5072.     mov    word ptr savsci+2,es     ;  and its segment
  5073.     mov    al,byte ptr modem.mdintv ; interrupt number for IRQ
  5074.     mov    dx,offset serint    ; offset of our interrupt routine
  5075.     push    ds            ; save ds around next DOS call
  5076.     mov    bx,cs            ; compose full address of our routine
  5077.     mov    ds,bx            ; segment is the code segment
  5078.     mov    ah,25H            ; set interrupt address from ds:dx
  5079.     int    dos
  5080.     pop    ds
  5081.     mov    al,rs232        ; interrupt number for Bios serial port
  5082.     mov    ah,35H            ; get vector into es:bx
  5083.     int    dos
  5084.     mov    word ptr sav232,bx    ; save offset
  5085.     mov    word ptr sav232+2,es    ; save segment
  5086.     mov    dx,offset serdum    ; offset of our interrupt routine
  5087.     push    ds            ; save ds around next DOS call
  5088.     mov    bx,cs            ; compose full address of our routine
  5089.     mov    ds,bx            ; segment is the code segment
  5090.     mov    ah,25H            ; set interrupt address from ds:dx
  5091.     int    dos
  5092.     pop    ds
  5093.     pop    es
  5094.     pop    bx
  5095.     mov    portin,1        ; Remember port has been initialized
  5096.     mov    ax,modem.mdstat
  5097.     mov    mst,ax            ; Use this address for status
  5098.     mov    ax,modem.mddat
  5099.     mov    mdat,ax            ; Use this address for data
  5100.     mov    ax,modem.mdiir
  5101.     mov    miir,ax            ; uart interrupt ident register
  5102.     cli                ; Disable interrupts
  5103.     cld                ; Do increments in string operations
  5104.     mov    al,modem.mdmeoi
  5105.     mov    mdeoi,al        ; Use to signify end-of-interrupt
  5106.     mov    dx,modem.mdmintc    ; interrupt controller cntl address
  5107.     mov    mdintc,dx
  5108.     inc    dx            ; access OCW1, interrupt mask byte
  5109.     in    al,dx            ; get 8259 interrupt mask
  5110.     and    al,modem.mden        ; enable IRQ. (bit=0 means enable)
  5111.     out    dx,al            ; rewrite interrupt mask byte
  5112.     mov    dx,modem.mdcom        ; set up serial card Line Control Reg
  5113.     in    al,dx            ; get present settings
  5114.     mov    savlcr,al        ; save them for restoration
  5115.     mov    al,3            ; 8 data bits. DLAB = 0
  5116.     out    dx,al
  5117.     mov    dx,modem.mddat
  5118.     inc    dx            ; int enable reg (03f9)
  5119.     in    al,dx
  5120.     mov    savier,al        ; save for restoration
  5121.     mov    dx,modem.mdiir        ; Interrupt Ident reg (03fah)
  5122.     in    al,dx            ; read current setting
  5123.     mov    al,087h    ; 8 byte trigger (80), reset fifos (2/4), Rx fifo(1) 
  5124.     out    dx,al
  5125.     jmp    $+2
  5126.     in    al,dx            ; read back iir
  5127.     and    al,0c0h    ; select BOTH fifo bits: 16550A vs 16550 (bad fifo)
  5128.     cmp    al,0c0h            ; are both fifo enabled bits set?
  5129.     je     serin2b            ; e = yes, rcvr fifo is ok (16550/A)
  5130.     xor    al,al            ; else turn off fifo mode (16550/etc)
  5131.     out    dx,al
  5132. serin2b:mov    dx,modem.mddat       ; data and command port, read and flush any    
  5133.     in    al,dx            ; char in UART's receive buffer
  5134.     inc    dx              ; interrupt enable register 3f9h
  5135.     mov    al,1            ; set up interrupt enable register
  5136.     out    dx,al            ;  for Data Available only
  5137.     jmp    $+2
  5138.     add    dx,3               ; modem control register 3fch
  5139.     in    al,dx            ; read original
  5140.     mov    savstat,al        ; save original
  5141.     mov    al,0bh          ; assert DTR, RTS, not OUT1, and OUT2
  5142.     cmp    dupflg,0        ; full duplex?
  5143.     je    serin2c            ; e = yes
  5144.     mov    al,9h            ; assert DTR, not RTS, not OUT1, OUT2
  5145. serin2c:out    dx,al          ; OUT2 high turns on interrupt driver chip
  5146.     sti
  5147.     jmp    serin4            ; finish up
  5148.  
  5149. serin3:    cmp    flags.comflg,'N'    ; NetBios?
  5150.     je    serin3o            ; e = yes
  5151.     cmp    flags.comflg,'O'    ; Opennet Network? (FGR)
  5152.     jne    serin3a            ; ne = no
  5153. serin3o:cmp    pcnet,2            ; already going?
  5154.     jne    serin3p            ; ne = no
  5155.     jmp    serin4            ; e = yes
  5156. serin3p:call    setnet            ; setup network session and pcnet flag
  5157.     jc    serin3q
  5158.     jmp    serin4            ; nc = success
  5159. serin3q:ret                ; fail, carry set, leave portin at 0
  5160. serin3a:cmp    flags.comflg,'E'    ; using EBIOS?
  5161.     jne    serin3b            ; ne = no
  5162.     mov    bx,offset ebcoms    ; es:bx to ebcoms structure
  5163.     mov    ebcoms+1,80h        ; force a network connection
  5164.     mov    ah,ebredir        ; do redirection
  5165.     xor    al,al
  5166.     mov    dx,ebport
  5167.     int    rs232
  5168.     or    ax,ax
  5169.     jz    serin3e            ; ax = 0 is success
  5170.     stc                ; fail
  5171.     ret
  5172. serin3e:mov    dx,ebport        ; port 0..3
  5173.     mov    bx,offset source    ; receive buffer for EBIOS
  5174.     push    es
  5175.     mov    ax,ds
  5176.     mov    es,ax            ; set es:bx to the buffer address
  5177.     mov    cx,bufsiz        ; set cx to buffer's length
  5178.     mov    ax,ebbufset*256+2    ; set rcvr buffered mode
  5179.     int    rs232
  5180.     mov    ax,ebmodem*256+3    ; set outgoing DTR and RTS modem leads
  5181.     int    rs232            ;  and ignore incoming leads
  5182.     mov    pcnet,1
  5183.     pop    es
  5184. serin3b:cmp    flags.comflg,'D'    ; DECnet?
  5185.     jne    serin3c            ; ne = no
  5186.     call    decstrt            ; reinit
  5187.     jnc    serin4            ; nc = success
  5188.     ret                ; fail, carry set, leave portin at 0
  5189. serin3c:cmp    flags.comflg,'T'    ; Novell TELAPI?
  5190.     jne    serin3d            ; ne = no
  5191.     cmp    pcnet,2            ; going already?
  5192.     je    serin4            ; e = yes
  5193.     call    telstrt            ; start Telnet session
  5194.     jnc    serin4            ; nc = success
  5195.     call    nethangup
  5196.     ret                ; fail, leave portin at 0
  5197. serin3d:cmp    flags.comflg,'I'    ; TES?
  5198.     jne    serin3f            ; ne = no
  5199.     call    tesstrt            ; start a TES session
  5200.     jnc    serin4            ; nc = success
  5201.     mov    ax,2000            ; pause 2 sec for any msg
  5202.     call    pcwait
  5203.     stc
  5204.     ret
  5205. serin3f:cmp    flags.comflg,'t'    ; TCP/IP?
  5206.     jne    serin4            ; ne = no
  5207.     call    tcpstart        ; start TCP connection
  5208.     jnc    serin4
  5209.     call    nethangup
  5210.     stc
  5211.     ret                ; fail
  5212. serin4:    push    bx
  5213.     mov    bx,portval        ; get port data structure
  5214.     mov    [bx].portrdy,1        ; say the comms port is ready
  5215.     mov    parmsk,0ffh        ; parity mask, assume parity is None
  5216.     cmp    [bx].parflg,parnon    ; is it None?
  5217.     je    serin1            ; e = yes
  5218.     mov    parmsk,07fh        ; no, pass lower 7 bits as data
  5219. serin1:    xor    ax,ax
  5220.     mov    al,[bx].floflg        ; flow control kind
  5221.     mov    flowcnt,al        ; save here for active use
  5222.     mov    ax,[bx].flowc        ; get flow control chars
  5223. serin1a:mov    flowoff,al        ; xoff or null
  5224.     mov    flowon,ah        ; xon or null
  5225.     mov    xofrcv,off        ; clear xoff received flag
  5226.     pop    bx
  5227.     mov    quechar,0        ; clear outchr queued flow control
  5228.     mov    portin,1        ; say initialized
  5229.     clc                ; carry clear for success
  5230.     ret                ; We're done
  5231. SERINI    ENDP
  5232.  
  5233. ; Reset the serial port.  This is the opposite of serini.  Calling
  5234. ; this twice without intervening calls to serini should be harmless.
  5235. ; Moved push/pop es code to do quicker exit before interrupts enabled. [jrd] 
  5236. ; Returns normally.
  5237. ; 22 June 1986 Leave OUT1 low to avoid resetting Hayes 1200B's. [jrd]
  5238. ; 21 Feb 1987 Add support for Bios calls [jrd]
  5239. ; 17 May 1987 Redo for COM3/4 support [jrd]
  5240. ; 9 July 1989 Accomodate 16550/A receiver fifo mode. [jrd]
  5241. SERRST    PROC    NEAR
  5242.     cmp    portin,0        ; Reset already? 
  5243.     jg    srst3            ; g = no
  5244.     clc
  5245.     ret                ; e = yes, l=not used yet, just leave
  5246. srst3:    cmp    flags.comflg,'0'    ; Bios or networks?
  5247.     jb    srst4            ; b = no, real UART
  5248.     jmp    srst1            ; nz = yes (Bios or Net)
  5249. srst4:    push    word ptr savsci        ; save original interrupt owner
  5250.     push    word ptr savsci+2    ; offset and segment
  5251.     mov    word ptr savsci,offset nulint ; redirect to our null routine
  5252.     mov    ax,cs            ; segment of null routine is code
  5253.     mov    word ptr savsci+2,ax
  5254.     xor    cx,cx            ; loop counter
  5255. srst2:    mov    dx,modem.mdstat        ; status register
  5256.     in    al,dx
  5257.     jmp    $+2            ; chip access delay
  5258.         and     al,60h            ; Shift Reg Empty & Holding Reg Empty
  5259.         cmp     al,60h            ; are both set?
  5260.         loopne  srst2               ; ne = no, wait until so (or timeout)
  5261.     xor    al,al
  5262.     mov    dx,modem.mdiir        ; modem Interrupt Ident reg (03fah)
  5263.     out    dx,al            ; turn off FIFO mode
  5264.     jmp    $+2
  5265.     dec    dx            ; point at int enable reg 3f9h
  5266.     out    dx,al            ; disable interrupts from this source
  5267.     jmp    $+2            ; let stray interrupts occur now
  5268.     jmp    $+2
  5269.     add    dx,2            ; point at Line Control Register 3fbh
  5270.     mov    al,savlcr        ; saved bit pattern
  5271.     and    al,not 80h        ; force DLAB bit to 0
  5272.     out    dx,al            ; restore line control state
  5273.         ; clear modem's delta status bits and reassert DTR etc
  5274.     inc    dx        ; increment to modem control register 3fch
  5275. ;;;;;    mov    al,03h        ; reassert DTR,RTS,but not OUT1 and not OUT2
  5276.     mov    al,savstat        ; saved modem control reg (03fch)
  5277.     or    al,3            ; ensure DTR and RTS are asserted
  5278.     cmp    dupflg,0        ; full duplex?
  5279.     je    srst2a            ; e = yes
  5280.     xor    cx,cx
  5281.     push    dx            ; save dx around test below
  5282. srst2b:    mov    dx,modem.mdstat        ; modem line status reg
  5283.     in    al,dx            ; read transmitter shift reg empty bit
  5284.     jmp    $+2
  5285.     jmp    $+2
  5286.     jmp    $+2            ; wait for char to be sent
  5287.     test    al,40h            ; is it empty?
  5288.     loopz    srst2b            ; z = no, not yet
  5289.     pop    dx
  5290.     mov    al,savstat        ; saved modem control reg
  5291.     or    al,1            ; assert DTR
  5292.     and    al,not 2        ; unassert RTS
  5293. ;;;;    mov    al,1            ; reassert DTR but not RTS, OUT1, OUT2
  5294. srst2a:    out    dx,al            ; restore modem control reg (03fch)
  5295.     jmp    $+2        ; pause, in case stray interrupt is generated
  5296.     jmp    $+2        ; which is more than likely, hence nulint.
  5297.     add    dx,2            ; modem status register 3feh
  5298.     in    al,dx            ; clear status register by reading it
  5299.     jmp    $+2
  5300.     mov    mdmhand,al        ; save here for Show Modem
  5301.     cli                ; Disable interrupts
  5302.     mov    dx,modem.mdmintc
  5303.     inc    dx
  5304.     in    al,dx            ; Interrupt controller int mask
  5305.     or    al,modem.mddis        ; inhibit our IRQ line
  5306.     jmp    $+2
  5307.     out    dx,al
  5308.     pop    word ptr savsci+2    ; recover original int owner's addr
  5309.     pop    word ptr savsci
  5310. ;;;    sti                ; replace original IRQ intrpt vector
  5311.     push    bx
  5312.     mov    al,byte ptr modem.mdintv ; vector number to do
  5313.     mov    dx,word ptr savsci     ; offset part
  5314.     push    ds
  5315.     mov    bx,word ptr savsci+2    ; segment part
  5316.     mov    ds,bx            ; ds:dx has interrupt vector
  5317.     mov    ah,25H            ; set interrupt vector
  5318.     int    dos            ; replaced
  5319.     pop    ds
  5320.     mov    al,rs232    ; Bios serial port interrupt vector to restore
  5321.     mov    dx,word ptr sav232    ; offset part
  5322.     push    ds
  5323.     mov    bx,word ptr sav232+2    ; segment part
  5324.     mov    ds,bx
  5325.     mov    ah,25h            ; set interrupt vector
  5326.     int    dos
  5327.     pop    ds
  5328.     pop    bx
  5329.     cli
  5330.     mov    ah,savirq        ; saved Interrupt state
  5331.     and    ah,modem.mddis        ; pick out our IRQ bit
  5332.     mov    dx,modem.mdmintc    ; interrupt controller cntl address
  5333.     inc    dx
  5334.     in    al,dx            ; get current intrpt controller state
  5335.     jmp    $+2
  5336.     and    al,modem.mden        ; set our bit to zero
  5337.     or    al,ah            ; set previous state of our IRQ
  5338.     out    dx,al            ; reset IRQ to original state
  5339.     sti
  5340.     mov    dx,modem.mddat        ; base address, 03f8h
  5341.     inc    dx                  ; Interrupt Enable Eeg (03f9h)
  5342.     mov    al,savier        ; saved IER
  5343.     out    dx,al            ; restore setting
  5344.     jmp    short srst8
  5345.                     ; non-UART processes
  5346. srst1:    cmp    flags.comflg,'E'    ; using EBIOS?
  5347.     jne    srst6            ; ne = no
  5348.     mov    dx,ebport        ; port 0..3
  5349.     mov    ah,ebcontrol        ; do a Regain Control operation
  5350.     int    rs232
  5351. srst1a:    mov    ax,ebbufcnt*256+2    ; see if rcvr buffer has chars already
  5352.     int    rs232
  5353.     jcxz    srst8            ; z = no, ok to reset buffering
  5354.     mov    ah,ebrcv        ; do receive /nowait to clear buff
  5355.     int    rs232
  5356.     jmp    short srst1a        ; repeat til empty
  5357.  
  5358. srst6:    cmp    pcnet,0            ; a network active?
  5359.     je    srst8            ; e = no
  5360.     cmp    flags.comflg,'O'    ; Opennet network? (FGR)
  5361.     je      srst7            ; e = yes
  5362.      cmp    flags.comflg,'N'    ; NetBios network?
  5363.       jne    srst8            ; ne = no
  5364. srst7:    cmp    rposted,0        ; receive outstanding?
  5365.     je    srst8            ; e = no
  5366.     mov    can.scb_baddr,offset rcv ; cancel receives
  5367.     push    bx
  5368.     mov    bx,offset can
  5369.     call    session
  5370.     pop    bx
  5371.     mov    rposted,0        ; clear interlock flag no matter what
  5372. srst8:    mov    portin,0        ; reset flag
  5373.     push    bx
  5374.     mov    bx,portval        ; port data structure
  5375.     mov    [bx].portrdy,0        ; say port is not ready
  5376.     pop    bx
  5377.     mov    quechar,0        ; clear any outchr queued char
  5378.     clc
  5379.     ret
  5380. SERRST    ENDP
  5381.  
  5382. ; Null interrupt routine, to handle strays
  5383. nulint    proc    near
  5384.     push    ax
  5385.     push    dx
  5386.     mov    al,mdeoi        ; specific EOI
  5387.     mov    dx,mdintc        ; interrupt controller control word
  5388.     out    dx,al
  5389.     test    dl,80h            ; slave controller?
  5390.     jz    nulint1            ; z = no
  5391.     mov    al,20h            ; general EOI
  5392.     out    20h,al            ; EOI to master 8259
  5393. nulint1:pop    dx
  5394.     pop    ax
  5395.     iret
  5396. nulint    endp
  5397.  
  5398. ; Dummy Interrupt 14H to defeat DOS interference with serial port when CTTY
  5399. ; and Kermit use the port simultaneously. If ports differ then chain DOS to
  5400. ; original Int 14H Bios code. Else return dummy status=ok reports and
  5401. ; Backspace for Read, ignore char for Write.
  5402. ; Entered with AH = function request, AL = char to be sent, DX = com port num
  5403. ; CS is our code segment, DS is DOS's, SS is ours or DOS's, interrupts off.
  5404. ; 25 June 1987 [jrd]
  5405. SERDUM    PROC    FAR
  5406.     push    ds            ; preserve all registers
  5407.     push    ax
  5408.     mov    ax,seg data        ; get our data segment
  5409.     mov    ds,ax
  5410.     mov    al,flags.comflg        ; get port id (COM1 = 1, COM2 = 2)
  5411.     and    al,7            ; use lower three bits
  5412.     dec    al            ; DOS counts COM1 as 0, etc
  5413.     mov    dosctty,0        ; assume DOS not using our comms line
  5414.     cmp    dl,al        ; referencing same port as Kermit is using?
  5415.     pop    ax            ; recover request parameters
  5416.     jne    serdu1            ; ne = no, chain to Bios routine
  5417.     mov    dosctty,1        ; say DOS is using our comms line
  5418.     pop    ds
  5419.     cmp    ah,1            ; send char in al?
  5420.     jb    serdu3            ; b = no, init, return dummy status=ok
  5421.     ja    serdu2            ; a = no, other
  5422.     mov    ah,60h            ; yes, set line status=ok in ah
  5423.     iret
  5424. serdu2:    cmp    ah,2            ; receive char (and wait for it)?
  5425.     jne    serdu3            ; ne = no, return dummy report
  5426.     mov    al,BS            ; yes, return ascii BS to DOS
  5427.     xor    ah,ah            ; ah = errors (none here)
  5428.     iret
  5429. serdu3:    mov    ax,60b0h        ; dummy status report:xmtr empty, CD,
  5430.     iret                ;  DSR, and CTS are on
  5431.  
  5432. serdu1:    pop    tempdum            ; save old ds
  5433.     push    word ptr sav232+2    ; push Bios int 14H handler segment
  5434.     push    word ptr sav232        ; push Bios int 14H handler offset
  5435.     push    tempdum            ; recover old ds
  5436.     pop    ds
  5437.     ret                ; do a ret far (chain to Bios)
  5438. SERDUM    ENDP
  5439.  
  5440. ; Serial port interrupt routine.  This is not accessible outside this
  5441. ; module, handles serial port receiver interrupts.
  5442. ; Revised on 22 May 1986, again 2 August 1986 to run at 38.4kb on PC's.
  5443. ; Srcpnt holds offset, within buffer Source, where next rcv'd char goes.
  5444. ; Count is number of chars now in buffer, and oldest char is srcpnt-count
  5445. ; done modulo size of Source. All pointer management is handled here.
  5446. ; Control-G char substituted for char(s) lost in overrun condition.
  5447. ; Upgraded to read cause of interrupt from interrupt ident reg (accepts only
  5448. ;  data ready), chain to old interrupt if source is not our device.
  5449. ; 9 Feb 1988 Add storage of interrupt cause in intkind. [jrd]
  5450. ; 9 July 1989 Add support for 16550/A 14 char receiver fifo.
  5451.  
  5452. SERINT  PROC  FAR
  5453.      push    ax            ; save registers
  5454.     push    dx            ; 
  5455.     push    ds
  5456.     mov    ax,seg data
  5457.     mov    ds,ax            ; address data segment
  5458.     mov    dx,miir            ; modem interrupt ident reg
  5459.     in    al,dx            ; get interrupt cause
  5460.     mov    intkind,al        ; save cause here
  5461.     test    al,1        ; interrupt available if this bit is zero
  5462.     jz    srintc            ; z = interrupt is from our source
  5463.     pop    tempsci            ;  save old ds
  5464.     pop    dx        ;  clean the stack and prepare for ret far
  5465.     pop    ax        ;  to old int handler (same as a jump there)
  5466.     push    word ptr savsci+2    ; old handler segment
  5467.     push    word ptr savsci        ; old handler offset
  5468.     push    tempsci            ; recover old ds
  5469.     pop    ds
  5470.     ret                ; do far return (chain to old handler)
  5471. srintc:    mov    al,mdeoi        ; specific EOI
  5472.     mov    dx,mdintc        ; interrupt controller control word
  5473.     out    dx,al
  5474.     test    dl,80h            ; slave controller?
  5475.     jz    srintd            ; z = no
  5476.     mov    al,22h            ; specific EOI for IRQ 2 (cascade)
  5477.     out    20h,al            ; EOI the master 8259
  5478. srintd:    test    intkind,4        ; data ready?
  5479.     jnz    srint0a            ; nz = yes, else ignore
  5480. srint0:    sti                ; else turn on interrupts
  5481.     jmp    retint            ;  and exit now (common jump point)
  5482.  
  5483. srint0a:mov    dx,mst            ; asynch status    port
  5484.     in    al,dx
  5485. srint0b:cli                ; no interrupts permitted here
  5486.     and    al,mdmover        ; select overrun bit
  5487.     mov    ah,al            ; save it for later
  5488.     mov    dx,mdat
  5489.     in    al,dx            ; read the received character into al
  5490.     test    flowcnt,1        ; XON/XOFF flow control active?
  5491.     jz    srint2            ; z = no
  5492.     mov    dh,al               ; dh = working copy. Check flow cntl
  5493.     and    dh,parmsk        ; strip parity temporarily, if any
  5494.     cmp    dh,flowoff        ; acting on Xoff?
  5495.     jne    srint1            ; ne = no, go on
  5496.     cmp    xofsnt,0        ; have we sent an outstanding XOFF?
  5497.     jne    srint4e            ; ne = yes, ignore (possible echo)
  5498.     mov    xofrcv,bufon        ; set the flag saying XOFF received
  5499.     jmp    short srint4e        ;  and continue the loop
  5500. srint1:    cmp    dh,flowon        ; acting on Xon?
  5501.     jne    srint2            ; ne = no, go on
  5502.     mov    xofrcv,off        ; clear the XOFF received flag
  5503.     jmp    short srint4e        ;  and continue the loop
  5504. srint2:    push    bx            ; save register
  5505.     or    ah,ah            ; overrun?
  5506.     jz    srint2a            ; z = no
  5507.     mov    ah,al            ; yes, save present char
  5508.     mov    al,bell            ; insert control-G for missing char 
  5509. srint2a:mov    bx,srcpnt        ; address of buffer storage slot
  5510.     mov    byte ptr [bx],al       ; store the new char in buffer "source"
  5511.     inc    srcpnt            ; point to next slot
  5512.     inc    bx
  5513.     cmp    bx,offset source + bufsiz ; beyond end of buffer?
  5514.     jb    srint3            ; b = not past end
  5515.     mov    srcpnt,offset source     ; wrap buffer around
  5516. srint3:    cmp    count,bufsiz        ; filled already?
  5517.     jae    srint4            ; ae = yes
  5518.     inc    count            ; no, add a char
  5519. srint4:    or    ah,ah            ; anything in overrun storage?
  5520.     jz    srint4a            ; z = no
  5521.     mov    al,ah            ; recover any recent char from overrun
  5522.     xor    ah,ah            ; clear overrun storage
  5523.     jmp    short srint2a        ; yes, go store real second char
  5524. srint4a:pop    bx            ; restore reg
  5525. srint4e:sti                 ; ok to allow interrupts now, not before
  5526.     mov    dx,mst            ; uart line status register
  5527.     in    al,dx            ; get status
  5528.     test    al,1            ; data ready?
  5529.     jnz    srint0b            ; nz = yes, and preserve al
  5530.     cmp    count,mntrgh        ; past the high trigger point?
  5531.     jbe    retint            ; be = no, we're within our limit
  5532.     test    xofsnt,bufon        ; has an XOFF been sent by buffer control?
  5533.     jnz    retint            ; nz = Yes
  5534.     test    flowcnt,2        ; using RTS/CTS flow control?
  5535.     jz    srint4b            ; z = no
  5536.     mov    dx,mst            ; modem status port (03fdh)
  5537.     dec    dx            ; modem control reg (03fch)
  5538.     in    al,dx
  5539.     and    al,not 2        ; reset RTS bit
  5540.     jmp    $+2
  5541.     out    dx,al            ; tell the UART to drop RTS
  5542.     mov    xofsnt,bufon           ; remember RTS reset at buffer level
  5543.     jmp    short retint
  5544.  
  5545. srint4b:mov    al,flowoff        ; get the flow off char (XOFF or null)
  5546.     or    al,al            ; do not send null chars
  5547.     jz    retint            ; z = null, nothing to send
  5548.     push    bx
  5549.     mov    bx,portval
  5550.     cmp    [bx].baud,Bsplit    ; doing 75/1200 baud stuff?
  5551.     pop    bx
  5552.     jne    srint4c            ; ne = no
  5553.     mov    quechar,al        ; put char in outchr queue for sending
  5554.     cmp    timeract,0        ; is timer being used at task level?
  5555.     jne    srint4d            ; ne = yes, just queue the char
  5556.     mov    ah,al            ; put char into ah
  5557.     call    outchr            ; send the char now, non-blocking
  5558. srint4d:jmp    short retint
  5559.  
  5560. srint4c:call    dopar            ; set parity appropriately
  5561.     mov    ah,al               ; don't overwrite character with status
  5562.     push    cx            ; save reg
  5563.     xor    cx,cx            ; loop counter
  5564. srint5:    mov    dx,mst            ; get port status
  5565.     in    al,dx
  5566.     test    al,20H            ; transmitter ready?
  5567.     jnz    srint6            ; nz = yes
  5568.     jmp    $+2            ; use time, prevent overdriving UART
  5569.     loop    srint5            ; else wait loop, cx times
  5570.     jmp    short srint7        ; timeout
  5571. srint6:    mov    al,ah            ; now send out the flow control char
  5572.     mov    dx,modem.mddat
  5573.     jmp    $+2
  5574.     out    dx,al
  5575.     mov    xofsnt,bufon       ; remember we sent an XOFF at buffer level
  5576. srint7:    pop    cx            ; restore reg
  5577. retint:    pop    ds
  5578.     pop    dx
  5579.     pop    ax
  5580.     iret
  5581. SERINT    ENDP
  5582.  
  5583. DTRLOW    PROC    NEAR        ; Global proc to Hangup the Phone or Network
  5584.                 ; by making DTR and RTS low (phone).
  5585.     mov    ah,cmword    ; allow text, to be able to display help
  5586.     mov    dx,offset rdbuf        ; dummy buffer
  5587.     mov    bx,offset hnghlp    ; help message
  5588.     call    comnd
  5589.     jc    dtrlow3            ; c = failure
  5590.     mov    ah,cmeol
  5591.     call    comnd            ; get a confirm
  5592.     jc    dtrlow3
  5593.     cmp    flags.comflg,'0'    ; Bios?
  5594.     jb    dtrlow1            ; b = no, UART
  5595.     cmp    flags.comflg,'4'    ; Bios?
  5596.     jbe    dtrlow2            ; be = yes, can't access modem lines
  5597. dtrlow1:call    serhng            ; drop DTR and RTS
  5598.     cmp    taklev,0        ; in a Take file or macro?
  5599.     jne    dtrlow2            ; ne = yes, no message
  5600.     mov    ah,prstr        ; give a nice message
  5601.     mov    dx,offset hngmsg
  5602.     int    dos
  5603. dtrlow2:clc                ; success
  5604. dtrlow3:ret
  5605. DTRLOW    ENDP
  5606.  
  5607. ; Hang up the Phone. Similar to SERRST except it just forces DTR and RTS low
  5608. ; to terminate the connection. 29 March 1986 [jrd]
  5609. ; 5 April 1987 Add 500 millisec wait with lines low before returning. [jrd]
  5610. ; Calling this twice without intervening calls to serini should be harmless.
  5611. ; If network then call nethangup procedure to hangup the session without
  5612. ; losing local name information.
  5613. ; Returns normally.
  5614.  
  5615. serhng    proc    near    ; clear modem's delta status bits and lower DTR & RTS
  5616. ;;;;    call    serini            ; init port, if not done already
  5617.     mov    al,flags.comflg        ; get kind of port
  5618.     cmp    al,4            ; UART?
  5619.     jbe    shng1            ; be = yes
  5620.     cmp    al,'4'            ; Bios?
  5621.     ja    shng3            ; a = no, networks
  5622.     clc                ; else Bios, no hangup
  5623.     ret
  5624. shng3:    cmp    flags.comflg,'E'    ; EBIOS?
  5625.     jne    shng2            ; ne = no
  5626.     mov    dx,ebport
  5627.     mov    ax,ebmodem*256+0    ; reset outgoing DTR and RTS leads
  5628.     int    rs232
  5629.     mov    ah,ebredir        ; do redirect away from EBIOS
  5630.     mov    ebcoms+1,0        ; set port to hardware
  5631.     int    rs232
  5632.     jmp    short shng2e
  5633. shng2:    call    nethangup        ; break the session
  5634. shng2e:    call    serrst            ; reset port so can be opened again
  5635.     clc
  5636.     ret
  5637. shng1:    call    serrst            ; reset port so serini can set DTR
  5638.     call    serini            ; energize, maybe for first time
  5639.     call    serrst            ; back to sleep
  5640.     cli                ; Disable interrupts
  5641.     push    ax
  5642.     push    dx
  5643.     mov    dx,modem.mddat        ; serial port base address
  5644.     add    dx,4            ; increment to control register
  5645.     mov    al,08h               ; reassert OUT2, un-assert DTR,RTS,OUT1
  5646.     out    dx,al
  5647.     jmp    $+2
  5648.     add    dx,2            ; increment to modem status register
  5649.     in    al,dx            ; Clear Status reg by reading it
  5650.     sti                ; Enable interrupts
  5651.     mov    ax,500            ; 500 millisec, for pcwait
  5652.     call    pcwait            ; keep lines low for at least 500 millisec
  5653.     call    serini            ; energize port to set DTR high again
  5654.     call    serrst            ; leave port off for CTTY actions
  5655.     pop    dx
  5656.     pop    ax
  5657.     clc
  5658.     ret
  5659. serhng    endp
  5660.  
  5661. code    ends 
  5662.     end
  5663.